Presentation is loading. Please wait.

Presentation is loading. Please wait.

嵌入式操作系统 陈香兰 Spring 2006 中国科学技术大学计算机系.

Similar presentations


Presentation on theme: "嵌入式操作系统 陈香兰 Spring 2006 中国科学技术大学计算机系."— Presentation transcript:

1 嵌入式操作系统 陈香兰 xlanchen@ustc.edu.cn xlanchen@ustc.edu.cn http://staff.ustc.edu.cn/~xlanchen Spring 2006 中国科学技术大学计算机系

2 第三部分 基于 Linux 的应用编程基础 Linux 中的信号 进程间通信 驱动程序编写

3 Linux 中的信号 xlanchen@2006.6.21

4 信号 信号在最早的 Unix 系统中就已经被引入了,用 于在用户态进程间通信。 内核也用信号通知进程系统所发生的事情

5 信号 信号是很短的消息 标准信号 标准信号没有给参数、消息或是其他相随的信息留 有空间 通常使用一个数字来标识一个信号 信号可以被发送到一个进程或一组进程。

6 软件中断的概念 信号的产生和处理方式跟中断有些相似 信号是典型的异步事件(当然也有一些事件是同步错误或异 常) 大多数产生信号的事件对进程而言是随机出现 进程不可能做轮询来测试某个标志位或者变量来判别是否发 生了一个信号,而是必须告诉内核 “ 在某个信号发生时,应 该执行如下操作 ” ,这点跟中断处理例程相似,所以也不难 理解标准信号不带参数或者是其他的信息 跟硬件中断一样,任何动作,包括终止进程,都只能由接收 到信号的进程来执行,也就是在本进程的上下文中执行

7 信号的作用 使用信号的两个主要目的是: 让进程知道已经发生了一个特定的事件 强迫进程执行它自己代码中的信号处理程序 很多应用程序提供自己的信号处理程序 系统也会定义一些缺省的信号处理程序

8 信号的生成 异常 当一个进程出现异常(比如试图执行一个非法指令,除 0 , 浮点溢出等),内核通过向进程发送一个信号来通知进程异 常的发生 其他进程 一个进程可以通过 kill 或是 sigsend 系统调用向另一个进程或 一个进出组发送信号。一个进程也可以向自身发送信号 终端 某些键盘字符如 ctrl+c 等会向终端的前台进程发送信号

9 作业控制 发送信号给那些想要读或写终端的后台进程。比如 shell 使用 信号来管理前台和后台进程 配额限制 当一个进程使用超过分配给它的 cpu 时间或是文件大小的限 制,内核发送一个信号给这个进程 通知 一个进程也许要求能被通知某些事件的发生。比如设备已经 就绪等待 I/O 操作 闹钟 定时器产生的信号,由内核发送给进程

10 Linux/i386 中的部分信号

11 信号举例: “Ctrl+c” 组合键 假设用户在 console 下按下 ctrl+c ,这将产生终端 中断 tty 驱动程序能识别出这个组合键,并向自己的前台进 程发送一个 SIGINT 信号。 当对应进程被调度执行时,它将在上下文切换返回到 用户态时检查到这个信号。 此外,通常前台进程就是被 ctrl+c 中断的 current 进程。 当进程从中断返回时,也会检查到这个信号。 检查到信号后,系统就会让进程执行相应的动作。

12 信号举例:异常 前面讲过,异常也是通过信号来实现的。 当程序发生除 0 错误或是有非法指令时,将引起 一个内核态的 trap 。 内核 trap 处理程序识别出这个异常并发送合适的 信号到当前进程。 当 trap 处理程序将要返回到用户态时,会检查并 发现信号,进程可能就会被终止。

13 异常处理程序异常处理程序 异常处理程序发出的信号异常处理程序发出的信号

14 与信号相关的系统调用

15 信号传递的两个不同阶段 信号产生 内核更新进程描述符中跟信号相关的数据结构来表 示一个信号被发送给了这个进程 信号传递 内核强迫目标进程通过以下方式对信号作出反映: 或改变目标进程的执行状态, 或开始执行一个特定的信号处理程序, 或者两者都是

16 挂起信号 已经产生但还没有传递的信号称为挂起信号。 任何时候,一个进程仅存在给定类型的一个挂 起信号,同一进程同种类型的其他信号不被排 队,只被简单的丢弃。

17 信号的挂起时间长度往往不可预知,原因在于: 信号通常只被 current 进程传递 进程可以选择阻塞某种信号。这种情况下,在取消 阻塞之前进程将不接收这个信号 当进程执行一个信号处理程序函数时,通常屏蔽相 应的信号,即自动阻塞这个信号直到处理程序结束。 因此,所处理的信号的另一次出现不能中断信号处 理程序

18 信号的应答方式和响应时机 进程以三种方式对一个信号做出应答 1 ,显式的忽略这个信号 多数信号都可以使用这种方式进行处理。 2 ,执行系统默认的缺省操作,可以是: Terminate :进程被杀死 Dump :进程被杀死,且如果可能,创建包含进程上下 文的可用于调试的 core 文件

19 Ignore :简单的忽略信号 Stop :进程被停止,状态置为 TASK_STOPPED Continue :如果进程被挂起,则状态置为 TASK_RUNNING 。否则忽略该信号 3 ,捕获信号 为了执行用户希望的对某个事件的处理,可以由用户指 定某个信号的处理函数。

20 信号的应答方式和响应时机 注意 1 :阻塞 ≠ 忽略 阻塞仅仅推迟了传递的时间 忽略的信号总是被传递,但是没有进一步的操作 注意 2 :有两种信号不可以被显式的忽略、捕 获或阻塞: SIGKILL 和 SIGSTOP 。因为它们 向超级用户提供一种终止或停止进程的可靠的 方法

21 信号的应答方式和响应时机 内核在如下时机检查进程的信号 1 ,从系统调用 / 中断返回到用户态之前,在 ret_from_intr 中执行这个检查 这个检查几乎在每个定时中断时都发生(约 10ms ) 代码在 i386\kernel\entry.S 中 2 ,进程从一个可中断的事件醒来后

22 中断返回 系统调用返回 如果有信号要处理 Entry.S 中部分相关的代码

23

24 内核在处理信号时需要注意的地 方 记住每个进程阻塞哪些信号 当从内核态切换到用户态时,要检查是否有信号到达 进程 确定是否可以忽略信号。这发生在下列条件都满足时 目标进程没有被另一个进程跟踪 信号没有被阻塞 信号被目标进程忽略 处理这样的信号,即信号可能在进程运行期间的任一 时刻请求把进程切换到一个信号处理函数,并在这个 函数返回以后恢复原来进程的执行

25 与信号相关的数据结构 在进程描述符中与信号处理相关的字段有: 记录进程想阻塞的信号 = 2 2 组 ×32 位信号, 第一组 sig[0] 为 32 个标准信号 记录被挂起的信号 指出挂起的信号是什么 被挂起的信号的相 关信息组成的队列 信号处理描述符 指出共享 signal_struct 结构的进程个数 每个信号的处理方法 = 64 如果有信号被挂起,就设置这个标志,前面的 entry.S 就根据这个快速判断有无挂起信号, 并根据这个标志调用 do_signal

26 在 i386 体系结构上 action 数组中的每一个信号 的描述符包含下列域: sa_handler 或 sa_sigaction 这是一个联合,表示如何处理这个信号,可能的值包括: 1 , SIG_DFL ,即 0 ,表示执行缺省操作 2 , SIG_IGN ,即 1 ,表示忽略这个信号 3 ,指向一个信号处理程序的指针,表示按照用户指定 的程序处理

27 sa_flags :一个标志集,指明与信号处理相关的一 些其他信息 sa_mask :指定处理本信号时,应当屏蔽的信号

28

29 发送信号 内核通过调用 send_sig_info() send_sig(), force_sig() force_sig_info() 这几个函数发送信号。这些函数只是更新目标 进程的进程描述符相关的域。但在条件满足的 情况下它们可以唤醒进程让目标进程接收信号

30 接收信号 内核在返回到用户态时调用 do_signal() 来处理 非阻塞的挂起信号: 参数: struct pt_regs *regs;//pt_regs 结构,指向当前进 // 程内核态堆栈中保存的寄存器 sigset_t *oldset; // 信号处理程序执行时要屏蔽的 // 信号,实际上调用时为空

31 do_signal() 一位一位的检查当前被挂起的非 阻塞信号,对应于上面介绍的 action 结构中 指定的处理方法: 如果是 SIG_IGN (忽略信号) 不能被忽略的信号

32 如果是 SIG_DFL (缺省操作) 根据信号的类型, 使用 switch 语句 找到对应的缺省 处理方式

33 如果信号有一个专门的处理程序, do_signal 就调 用 handle_signal() 强迫执行该处理程序

34 Handle_signal 信号处理程序是用户态进程所定义的函数,并 且包含在用户态的代码段中 Handle_signal 运行在内核态,而信号处理程 序运行在用户态 问题: 1 ,必须返回用户态执行信号处理程序 2 ,必须按照原来进入内核的方式返回用户态 3 ,一旦返回用户态,内核堆栈就被清空,如何保存 内核堆栈的内容

35 Linux 采用的解决办法: 把保存在内核态堆栈中的上下文拷贝到当前进程的 用户态堆栈中 建立好信号处理程序所需的堆栈环境 当信号处理程序运行结束时,调用 sigreturn() 系统 调用把上面保存的内核堆栈的内容再拷贝回内核堆 栈 然后正常返回

36 与信号处理相关的系统调用 kill(pid, sig) 系统调用 发送信号,对应于 sys_kill() 对于 pid 的值 1 ,如果大于 0 ,发送信号给指定的进程 2 ,如果 =0 ,把信号发送给同组的所有进程 3 ,如果 =-1 ,把信号发送给除 0 号、 1 号以及 current 进程之外的所有进程 4 ,如果小于 -1 ,把信号发送给指定的进程组中的 所有的进程

37 sigaction(sig, act, oact) 系统调用 允许用户为信号指定一个操作,对应于 sys_sigaction() 参数: sig ,指明是哪一个信号 act ,指定新的操作 oact ,可选,用来存放旧的操作

38 signal(sig, handler) 系统调用 设置信号处理程序为 handler ,对应于 sys_singal()

39 用户设置信号处理程序举例: 演示。


Download ppt "嵌入式操作系统 陈香兰 Spring 2006 中国科学技术大学计算机系."

Similar presentations


Ads by Google