进程间通信-IPC.ppt_第1页
进程间通信-IPC.ppt_第2页
进程间通信-IPC.ppt_第3页
进程间通信-IPC.ppt_第4页
进程间通信-IPC.ppt_第5页
已阅读5页,还剩110页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

linux进程间通信 linux进程间通信 进程间通信IPC interprocessCommunication 提供了一种不同进程间可以互相访问数据的方式 相互访问的数据不仅包括程序运行时的适时数据 也包括对对方代码段的访问 进程间通信的目的 1 数据传输 一个进程需要将它的数据发送给另一个进程 发送的数据量在一个字节到几兆字节之间 2 共享数据 多个进程想要操作共享数据 一个进程对共享数据的修改 别的进程应该立刻看到 3 通知事件 一个进程需要向另一个或一组进程发送消息 通知它 它们 发生了某种事件 如进程终止时要通知父进程 4 资源共享 多个进程之间共享同样的资源 为了作到这一点 需要内核提供锁和同步机制 5 进程控制 有些进程希望完全控制另一个进程的执行 如Debug进程 此时控制进程希望能够拦截另一个进程的所有异常 并能够及时知道它的状态改变 linux进程间通信发展历史 linux进程间通信 IPC 由以下几部分发展而来 linux进程间通信方式 目前Linux中使用较多的进程间通信方式 1 管道 Pipe 及有名管道 namedpipe 管道可用于具有亲缘关系进程间的通信 有名管道 除具有管道所具有的功能外 它还允许无亲缘关系进程间的通信 2 信号 Signal 信号是在软件层次上对中断机制的一种模拟 它是比较复杂的通信方式 用于通知接受进程有某事件发生 一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一样的 3 消息 message 队列 消息队列是消息的链接表 包括Posix消息队列systemV消息队列 它克服了前两种通信方式中信息量有限的缺点 具有写权限的进程可以向消息队列中按照一定的规则添加新消息 对消息队列有读权限的进程则可以从消息队列中读取消息 linux进程间通信 4 共享内存 sharedmemory 可以说这是最有用的进程间通信方式 它使得多个进程可以访问同一块内存空间 不同进程可以及时看到对方进程中对共享内存中数据的更新 这种通信方式需要依靠某种同步机制 如互斥锁和信号量等 5 信号量 semaphore 主要作为进程间以及同一进程不同线程之间的同步手段 6 套接字 Socket 这是一种更为一般的进程间通信机制 它可用于不同机器之间的进程间通信 应用常广泛 管道通信 管道通信是linux中比较常见 也比较原始的通信方式之一 它实现了数据以一种数据流的方式 在多进程间流动 管道 是指用于连接一个读进程和一个写进程 以实现它们之间通信的共享文件 又称pipe文件 管道是单向的 先进先出的 无结构的 固定大小的字节流 它把一个进程的标准输出和另一个进程的标准输入连接在一起 写进程在管道的尾端写入数据 读进程在管道的首端读出数据 数据读出后将从管道中移走 其它读进程都不能再读到这些数据 管道提供了简单的流控制机制 进程试图读空管道时 在有数据写入管道前 进程将一直阻塞 同样 管道已经满时 进程再试图写管道 在其它进程从管道中移走数据之前 写进程将一直阻塞 管道分类 无名管道 匿名管道 在系统中没有实名 不能在文件系统中以任何方式看到该管道 它只是进程的一种资源 会随着进程的结束而被系统清除 有名管道 也称为FIFO管道 是一种文件类型 在文件系统中可以查看到 7 匿名管道 pipe 对匿名管道两端进程而言 是一个只存在于内存的特殊文件匿名管道是半双工的 数据只能向一个方向流动一个进程将数据写入管道 另一进程从管道中读取数据写入的内容添加在管道缓冲区的末尾 每次都是从缓冲区头部读出数据双向通信的建立需要建立起两个管道使用限制只能用于具有亲缘关系的进程之间如父子进程或兄弟进程之间 管道通信 8 匿名管道的建立 基本函数intpipe intfd 2 参数说明fd 2 描述管道两端fd 0 只能用于读 称为管道读端fd 1 只能用于写 称为管道写端若试图从写端读 或者向读端写都将导致错误发生返回值成功时返回0 失败时返回 1说明基本文件I O函数都可用于管道如close read write 等低层系统调用sys pipe do pipe 管道通信 9 匿名管道的读操作 进程调用read 系统调用内核最终调用与该文件描述符相关的文件操作表中所找到的read 方法在管道情形下 read方法将指向pipe read 函数该系统调用可能以两种方式阻塞当前进程系统调用开始时管道缓冲区为空管道缓冲区没有包含所请求的字节 n个字节 写进程在等待缓冲区的空间时曾经被置为睡眠 10 匿名管道的写操作 进程调用write 系统调用内核最终调用pipe write 函数如果管道没有读进程 写进程发送SIGPIPE信号管道缓冲区一有空闲区域 写进程将试图写入数据如果读进程不读出管道缓冲区中的数据 那么写操作将一直阻塞 匿名管道示例一 include include includeintmain void intfd 2 charstr 256 if pipe fd 0 perror pipe exit 1 write fd 1 Createthepipesuccessfully n 31 read fd 0 str sizeof str printf s n str close fd 0 close fd 1 return0 单个进程中的管道几乎没有任何用处 通常 调用pipe的进程接着调用fork 这样就创建了从父进程到子进程或反之的IPC通道 fork之后做什么取决于我们想要有的数据流的方向 对于从父进程到子进程的管道 父进程关闭管道的读端 fd 0 子进程则关闭写端 fd 1 对于从子进程到父进程的管道 父进程关闭fd 1 子进程关闭fd 0 12 include include include defineBUFSZ256intmain void intfd 2 charbuf BUFSZ pid tpid intlen if pipe fd 0 perror failedtopipe exit 1 if pid fork 0 perror failedtofork exit 1 13 elseif pid 0 printf Thisisfarther writetofd 1 n fd 0 fd 1 close fd 0 write fd 1 fartherwrite childread n 25 exit 0 else printf Thisischild readfromfd 0 n close fd 1 read fd 0 buf BUFSZ printf s n buf return0 匿名管道 父子进程间通信 匿名管道操作基本流程 管道操作的基本流程 1 使用pipe函数创建管道 2 用fork函数创建一个子进程 3 关闭父子进程中不需要的文件描述符 使用管道进行通信 由于以上对管道的操作是比较规范 也比较常用 所以在ANSIC中将以上操作定义在两个标准库函数中 分别是popen和pclose函数 FILE popen constchar command constchar type intpclose FILE fp 参数command是一个在shell中可以运行的命令字符串的指针 参数type是一个字符指针 这个参数只有两种值 分别是r和w 分别对应popen函数的返回值是一个读打开文件指针 还是写打开文件指针 函数失败返回NULL 并设置出错变量errno pclose函数的参数fp是一个popen打开的文件描述符 函数失败时返回 1 include include include include include defineBUFESPIPE BUFintmain void FILE fp char cmd ls l charbuf BUFES if fp popen cmd r NULL perror failedtoopen n exit 1 while fgets buf BUFES fp NULL printf s n buf pclose fp exit 0 Popen示例 16 有名管道 匿名管道缺点没有名字 只能用于具有亲缘关系的进程间通信FIFO 有名管道 严格遵循先进先出的读写规则有名字 FIFO的名字包含在系统的目录树结构中 支持无亲缘关系的进程按名字访问类似管道 在文件系统中不存在数据块 而是与一块内核缓冲区相关联read和write操作也由pipe read 和pipe write 实现与匿名管道主要区别FIFO索引节点出现在系统目录树上而不是pipefs特殊文件系统中FIFO是一种双向通信管道 可以以读 写模式打开一个FIFO 17 有名管道的建立 基本函数intmkfifo constchar pathname mode tmode 参数说明pathname 创建的FIFO名字mode 规定FIFO的读写权限返回值成功时返回0失败时返回 1若路径名存在 则返回EEXIST错误说明一般文件的I O函数都可用于管道 如open close read write 等 18 有名管道的open 打开规则为读操作而打开FIFO文件若已有进程为写而打开该FIFO 则当前打开操作将成功返回否则 可能阻塞直到有相应进程为写而打开该FIFO 当前打开操作设置未设置O NONBLOCK标志 或立即返回 当前打开操作设置O NONBLOCK标志 为写操作而打开FIFO文件如果已经有进程为读而打开该FIFO 则当前打开操作将成功返回否则 可能阻塞直到有相应进程为读而打开该FIFO 当前打开操作未设置O NONBLOCK标志 或者 返回ENXIO错误 当前打开操作设置O NONBLOCK标志 实例 1 mkfifotestfifo建立有名管道文件testfifo 2 ls testfifo向有名管道文件写入 ls 命令显示的内容 3 cattestfifo用 cat 命令读取 testfifo 文件中的内容 19 有名管道示例 创建有名管道 include include include include include include include includeintmain intargc char argv mode tmode 0666 mode tmode O NONBLOCK if argc 2 printf USEMSG create fifo fifoname n exit 1 if mkfifo argv 1 mode 0 perror failedtomkfifo exit 1 elseprintf yousuccessfullycreateaFIFOnameis s n argv 1 exit 0 20 有名管道举例 读有名管道 include include include include include include include include defineBUFESPIPE BUFintmain void intfd intlen charbuf BUFES if fd open testfifo O RDONLY 0 printf read s buf close fd return0 21 有名管道示例 写有名管道 include include include include include include include include defineBUFESPIPE BUFintmain void intfd intn i if fd open testfifo O WRONLY 0 perror open exit 1 for i 0 i 10 i if write fd message n 9 0 perror write exit 1 close fd return0 22 信号的本质 信号是一种进程间异步通信机制 可以看作是异步通知 通知接收信号的进程有哪些事情发生了 在实现上是一种软中断 是对中断的模拟 也称软中断信号或软中断 信号可以导致一个正在运行的进程被异步打断 让进程知道已经发生了一个特定事件 强迫进程执行自身代码中的信号处理程序 发给非运行进程的信号必须由内核保存 直到进程恢复执行 阻塞一个信号要求信号的传递被延迟 直到随后解除阻塞 每个信号都有名字 这些名字都是以SIG开头 不存在编号为0的信号 信号来源 硬件来源硬件操作 如按Ctrl C硬件故障软件来源常用信号发送函数 如kill raise alarm 非法运算 浮点运算溢出或内存访问错误等也可产生信号 24 信号分类 不可靠信号信号值小于SIGRTMIN 进程每次处理信号后 将信号响应函数设置为默认动作 需调用signal 重新安装信号 非实时信号都是不可靠信号 不支持排队 信号可能丢失 可靠信号信号值介于SIGRTMIN和SIGRTMAX之间 新信号安装函数sigaction 和信号发送函数sigqueue 实时信号都是可靠信号 支持排队 信号通信 25 进程对信号的响应方式 忽略信号进程忽略接收到的信号 不做任何处理 SIGKILL和SIGSTOP不能忽略 不能为SIGKILL和SIGSTOP设置新的信号处理函数 捕获信号类似中断处理程序 一旦捕获到相应信号 执行对应的信号处理函数 进程可通过signal sigaction 指定进程对某个信号的处理行为 缺省操作Linux内核为信号提供默认处理程序处理 26 常见信号 Kill l可列出所有信号 27 信号生命周期 信号诞生触发信号的事件发生 如检测到硬件异常 定时器超时以及调用信号发送函数kill 或sigqueue 等 信号在进程中注册内核更新目标进程的数据结构 将信号加入进程的未决信号集 并将信号所携信息保存到某个sigqueue结构中对实时信号 不管其是否已在进程中注册 都被再次注册对非实时信号 若该信号已在进程中注册 则将其丢弃信号在进程中注销进程从核心空间返回用户空间时都检测是否有信号等待处理若存在等待处理且未被阻塞的未决信号 则将其在未决信号链中占有的结构卸掉 对实时进程只删除sigqueue结构 信号处理函数执行完毕执行相应信号处理函数或改变目标进程的执行状态 28 信号在进程中注册 进程的task struct结构中有关于本进程中未决信号的数据成员 structsigpending中第三个成员signal是进程中所有未决信号集 第一 第二个成员分别指向一个sigqueue类型的链表的 称之为 未决信号信息链 的首尾 该链中的每个sigqueue结构包含一个特定信号所携带的信息 并指向下一个sigqueue结构 信号在进程中注销 在目标进程执行过程中 会检测是否有信号等待处理 每次从系统空间返回到用户空间时都做这样的检查 如果存在未决信号等待处理且该信号没有被进程阻塞 则在运行相应的信号处理函数前 进程会把信号在未决信号链中占有的结构卸掉 是否将信号从进程未决信号集中删除对于实时与非实时信号是不同的 对于非实时信号来说 由于在未决信号信息链中最多只占用一个sigqueue结构 因此该结构被释放后 应该把信号在进程未决信号集中删除 信号注销完毕 而对于实时信号来说 可能在未决信号信息链中占用多个sigqueue结构 因此应该针对占用sigqueue结构的数目区别对待 如果只占用一个sigqueue结构 进程只收到该信号一次 则应该把信号在进程的未决信号集中删除 信号注销完毕 否则 不应该在进程的未决信号集中删除该信号 信号注销完毕 进程在执行信号相应处理函数之前 首先要把信号在进程中注销 30 信号处理函数 信号发送函数kill sigqueue raise alarm setitimer pause abort 信号安装函数signal sigaction 信号集操作函数sigemptyset sigfillset sigaddset sigdelset sigismember 31 信号发送函数 kill include includeintkill pid tpid intsigno 功能向进程或进程组发送一个信号 成功返回0 否则 返回 1 参数说明pid 接收信号的进程 组 的进程号pid 0 发送给进程号为pid的进程pid 0 发送给当前进程所属进程组里的所有进程pid 1 发送给除1号进程和自身以外的所有进程pid 1 发送给属于进程组 pid的所有进程signo 发送的信号Signo 0 不发送信号 可用于检查目标进程是否存在 以及当前进程是否具有向目标进程发送信号的权限 root权限的进程可以向任何进程发送信号 非root权限的进程只能向属于同一个session或者同一个用户的进程发送信号 include include include include includeintmain void pid tchildpid intstatus intretval childpid fork if 1 childpid perror fork exit EXIT FAILURE elseif 0 childpid puts Inchildprocess sleep 100 让子进程睡眠 看看父进程的行为exit EXIT SUCCESS else if 0 waitpid childpid 33 信号发送函数 sigqueue include includeintsigqueue pid tpid intsigno constunionsigvalsigval t 调用成功返回0 否则 返回 1 功能主要针对实时信号 支持带有参数信号 与函数sigaction 配合使用参数说明pid 接收信号的进程IDsigno 待发送信号sigval t 信号传递的参数 4字节 说明调用sigqueue 时 sigval t被拷贝到信号处理函数sigqueue 发送非实时信号时sigval t包含的信息仍然能够传递给信号处理函数仍然不支持排队 所有相同信号都被合并为一个信号 34 sigqueue 向信号传递附加消息的流程 sigqueue 的第三个参数是sigval联合数据结构调用sigqueue 时 该数据结构中的数据将被拷贝到信号处理函数sigaction 的第二个参数这样 就可在发送信号的同时让信号传递一些附加信息 35 Kill 与sigqueue 区别 sigqueue 比kill 传递更多的附加信息sigqueue 只能向一个进程发送信号 信号通信 36 信号发送函数 raise includeintraise intsigno 功能向自身发送信号参数说明signo 发送的信号signo 0 不发送信号返回值成功时 返回0错误时 返回 1说明raise 可以通过kill 实现 raise signo 等价于kill getpid signo 信号通信 include includeintmain void printf killmyself n raise SIGKILL printf canyouseethis n return0 38 信号发送函数 alarm includeunsignedintalarm unsignedintseconds 功能设置定时器 当计时时间到达时 向进程发出SIGALRM信号参数说明seconds 等待秒数seconds为0时 取消先前设置的闹钟 返回闹钟剩余时间若之前未设闹钟 则返回0说明alarm 只发送一次信号若需重复设定定时器 则要多次调用alarm 函数 信号通信 include include include include includevoidhandler printf hellon n main inti signal SIGALRM handler alarm 5 for i 1 i 7 i printf sleep d n i sleep 1 40 信号发送函数 setitimer 函数原型intsetitimer intwhich conststructitimerval value structitimerval ovalue 参数说明which 逻辑定时器类型ITIMER REAL 按实际时间计时 计时到达时向进程发送SIGALRM信号 ITIMER VIRTUAL 计算进程在用户态执行的时间 计时到达将发送SIGVTALRM信号给进程 ITIMER PROF 计算进程在用户态和核心态的总时间 计时到达将发送SIGPROF信号给进程 与ITIMER VIRTUAL是一对 该定时器经常用来统计进程在用户态和核心态花费的时间value 指明定时器的时间ovalue 如果不为空 则保存上次调用设定的值功能指定一段时间后 执行某个function 每间格一段时间就执行某个function 41 信号发送函数 setitimer 续 返回值成功时 返回0错误时 返回 1structitimerval结构定义structitimerval structtimevalit interval 定时器周期 structtimevalit value 定时器剩的时间 为0时发信号 structtimeval结构定义structtimeval longtv sec 秒 longtv usec 微秒 1秒 1000000微秒 it value为0是不会触发信号的 所以要能触发信号 it value得大于0 如果it interval为零 只会延时 不会定时 也就是说只会触发一次信号 信号通信 42 信号发送函数 setitimer 示例 include include includevoidsignalHandler intsigno switch signo caseSIGALRM printf CaughttheSIGALRMsignal n break intmain intargc char argv signal SIGALRM signalHandler structitimervalnew value old value new value it value tv sec 1 new value it value tv usec 0 new value it interval tv sec 2 new value it interval tv usec 0 setitimer ITIMER REAL 43 信号发送函数 pause 功能使当前进程暂停 进入睡眠状态 直到被信号所中断 即将进程挂起等待信号到来 函数原型intpause void 返回值 1举例使用alarm 和pause 实现sleep 功能 44 信号发送函数 pause 示例 信号的安装 设置信号关联动作 如果进程要处理某一信号 那么就要在进程中安装该信号 安装信号主要用来确定信号值及进程针对该信号值的动作之间的映射关系 即进程将要处理哪个信号 该信号被传递给进程时 将执行何种操作 linux主要有两个函数实现信号的安装 signal sigaction 其中signal 在非可靠信号系统调用的基础上实现 是库函数 它只有两个参数 不支持信号传递信息 主要是用于前32种非实时信号的安装 而sigaction 是较新的函数 由两个系统调用实现 sys signal以及sys rt sigaction 有三个参数 支持信号传递信息 主要用来与sigqueue 系统调用配合使用 当然 sigaction 同样支持非实时信号的安装 sigaction 优于signal 主要体现在支持信号带有参数 46 信号安装函数 signal 原型定义void signal intsignum void handler int int 参数说明signum 需要安装的信号handler 与安装信号相关的处理函数 可以是SIG IGN或SIG DFLSIG IGN 忽略该信号SIG DFL 执行默认操作函数返回值成功时 返回新安装信号处理函数handler的值失败时 返回SIG ERR底层系统调用sys signal intsig sighandler thandler 47 信号安装函数 signal 示例 include include include includevoidsig usr intsig intmain intargc char argv inti 0 if signal SIGUSR1 sig usr SIG ERR printf Can tcatchSIGUSR1 n if signal SIGUSR2 sig usr SIG ERR printf Can tcatchSIGUSR2 n while 1 printf 2d n i pause i return0 voidsig usr intsig if sig SIGUSR1 printf ReceivedSIGUSR1 n elseif sig SIGUSR2 printf ReceivedSIGUSR2 n elseprintf Undeclaredsignal d n sig 执行 Gccsignal c osignal signal 以后台程序运行 并显示pid Kill SIGUSR1pid 49 信号安装函数 sigaction 原型定义intsigaction intsignum conststructsigaction act structsigaction oldact sigaction函数用于设定进程接收到特定信号后的行为 第一个参数为信号的值 可以为除SIGKILL及SIGSTOP外的任何一个特定有效的信号 为这两个信号定义自己的处理函数 将导致信号安装错误 第二个参数是指向结构sigaction的一个实例的指针 在结构sigaction的实例中 指定了对特定信号的处理 如果为空 进程会以缺省方式对信号处理 第三个参数oldact指向的对象用来保存原来对相应信号的处理 可指定oldact为NULL 如果把第二 第三个参数都设为NULL 那么该函数可用于检查信号的有效性 第二个参数最为重要 其中包含了对指定信号的处理 信号所传递的信息 信号处理函数执行过程中应屏蔽掉哪些函数等等 底层系统调用sys sigaction intsig conststructold sigaction user act structold sigaction user oact sigaction结构定义如下 sa restorer 已过时 POSIX不支持它 不应再被使用 联合数据结构中的两个元素 sa handler以及 sa sigaction指定信号关联函数 即用户指定的信号处理函数 除了可以是用户自定义的处理函数外 还可以为SIG DFL 采用缺省的处理方式 也可以为SIG IGN 忽略信号 由 sa handler指定的处理函数只有一个参数 即信号值 所以信号不能传递除信号值之外的任何信息 由 sa sigaction指定的信号处理函数带有三个参数 是为实时信号而设的 当然同样支持非实时信号 它指定一个3参数信号处理函数 第一个参数为信号值 第三个参数没有使用 posix没有规范使用该参数的标准 第二个参数是指向siginfo t结构的指针 结构中包含信号携带的数据值 参数所指向的结构如下 sa mask 信号的集合 指定在信号处理程序执行过程中 哪些信号应当被阻塞 缺省情况下当前信号本身被阻塞 防止信号的嵌套发送 注 sigaction 安装信号的处理函数执行过程中由sa mask指定的信号才被阻塞 sa flags用于更改指定信号的行为 比较重要的标志位是SA SIGINFO 当设定了该标志位时 表示信号附带的参数可以被传递到信号处理函数中 因此 应该为sigaction结构中的sa sigaction指定处理函数 而不应该为sa handler指定信号处理函数 否则 设置该标志变得毫无意义 即使为sa sigaction指定了信号处理函数 如果不设置SA SIGINFO 信号处理函数同样不能得到信号传递过来的数据 在信号处理函数中对这些信息的访问都将导致段错误 Segmentationfault 54 信号安装函数 sigaction 示例一 include include include includevoidmyFun intsig intmain intargc char argv structsigactionact oldact act sa handler myFun sigemptyset voidmyFun intsig printf Igotasignal d n sig Gccsigacton1 c osigaction sigaction Kill SIGUSR1pid 信号安装函 sigaction 数示例二 include include include includevoidfunc intsigno siginfo t info void p printf signo d n signo printf senderpid d n info si pid intmain structsigactionact oldact sigemptyset 在另外一个终端发送信号给当前进程 sigqueue 函数调用示例在不同进程间传递整型参数 信号接收程序 include include include include includevoidmyFun int siginfo t void myfun intmain intargc char argv structsigactionact intsig pid tpid pid getpid printf pidis d n pid sigemptyset 56 if sigaction SIGUSR1 sigqueue 函数调用示例在不同进程间传递整型参数 信号发送程序 include include include include include includemain intargc char argv pid tpid intsignum unionsigvalmysigval pid pid t atoi argv 1 mysigval sival int 8 if sigqueue pid SIGUSR1 mysigval 1 printf senderror n sleep 2 return0 57 signal 与sigaction 的区别 不同点signal 安装的信号不能向信号处理函数传递信息sigaction 可设置进程的信号掩码 返回设置之前的sigaction结构安装的信号可以向信号处理函数传递信息相同点都可以为指定的信号设置信号处理函数共用同一个内核函数do sigaction 58 59 信号集操作函数 信号集定义函数原型intsigemptyset sigset t set 初始化信号集合set 将set设置为空intsigfillset sigset t set 初始化信号集合 将信号集set设置为包含所有信号的集合intsigaddset sigset t set intsigno 将信号signo加入到信号集set中intsigdelset sigset t set intsigno 将信号signo从信号集set中删除intsigismember sigset t set intsigno 查询信号signo是否在信号集set中 60 信号操作函数 sigprocmask 功能通过信号集set修改进程的信号阻塞集函数原型intsigprocmask inthow constsigset t set sigset t oset 参数how 函数操作方式SIG BLOCK 增加一个信号集到当前进程的阻塞集中SIG UNBLOCK 从当前阻塞集中删除一个信号集SIG SETMASK 将当前信号集设置为信号阻塞集合set 当前进程的信号集oset 保存当前进程的信号阻塞集说明在使用之前需先设置好信号集合set 61 其他信号处理函数 sigpending sigset t set 获取当前进程的未决信号集set保存返回结果sigsuspend constsigset t mask 在接收到某个信号之前 临时用mask替换进程的信号掩码 并暂停进程执行 直到收到信号为止sigsuspend返回后将恢复调用之前的信号掩码信号处理函数完成后 进程将继续执行该系统调用始终返回 1 并将errno设置为EINTR task struct中与信号处理相关的成员 structsignal struct signal信号描述符结构 为每种信号选择处理函数structsighand struct sighand包含信号处理函数描述符的数组 信号作为数组序号sigset tblocked real blocked 被阻塞信号的掩码 每种信号类型对应一个元素structsigpendingpending 维护本进程中的未决信号sigset tsaved sigmask 保存信号掩码定义TIF RESTORE SIGMASK时恢复信号掩码 62 task struct信号处理相关数据结构关系图 63 64 SystemVIPC概述 IPC资源表示单独的消息队列 共享内存或信号量集合具有相同类型的接口函数信号量集合实现进程同步消息队列以异步方式为通信频繁 但数据量少的进程通信提供服务共享主存为数据量大的进程间通信提供服务共同点通过SystemVIPC对象通信时 需传递该对象的唯一IPC标识符访问SystemVIPC对象时必须经过许可检验SystemVIPC对象的访问权限由对象创建者设置 65 IPC对象标识符与IPC键 IPC标识符由内核分配给IPC对象 在系统内部唯一IPC对象标识符的获取 XXXget 将IPC键传递给以sys 打头的内核函数 并为用户分配一个与IPC对象相对应的数据结构返回一个32位IPC标识符 进程使用此标识符对该资源进行访问IPC键IPC对象的外部表示 可由程序员选择如果键是公用的 则系统中所有进程通过权限检查后 均可找到和访问相应IPC对象每个进程都可建立一个键值为IPC PRIVATE的私有IPC对象 66 IPC键的创建 创建函数key tftok char filename intid 功能说明将一个现存文件名 对应文件必须是可访问的 和一个整数标识符id转换成一个key t值在Linux系统中 调用该函数时 系统将该文件的索引节点号取出 并在前面加上子序号 从而得到key t返回值 IPC资源的全局定义 消息队列msgid ds 16个定义位置 proc sys kernel msgmni共享内存shmid ds 4096个定义位置 proc sys kernel shmmni信号量semid ds 128个定义位置 proc sys kernel sem 67 68 SystemVIPC的基本操作 操作函数 XXX代表msg sem shm三者之一 XXXget 获得IPC标识符XXXctl 控制IPC资源操作模式先通过XXXget 创建一个IPC资源 返回IPC标识符随后操作均以IPC资源标识符为参数 对相应IPC资源进行操作其他进程可通过XXXget 获取已有的IPC资源标识符 权限允许的话 并对其操作 请求IPC标识符时返回的错误码 69 70 主要内容 传统进程通信信号通信管道通信SystemVIPC进程通信消息队列共享主存信号量 71 消息队列 消息队列 也叫做报文队列 是一个消息的链表 可以把消息看作一个记录 具有特定的格式以及特定的优先级 对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息 对消息队列有读权限的进程则可以从消息队列中读走消息 IPC消息队列资源的限制IPC消息队列的缺省数为16每个消息的缺省最大值8192字节队列中全部信息的缺省大小为16384字节 消息队列模型 操作消息队列 1 打开或创建消息队列 2 读写操作 消息读写操作非常简单 对开发人员来说 每个消息都类似如下的数据结构 mtype成员代表消息类型 从消息队列中读取消息的一个重要依据就是消息的类型 mtext是消息内容 当然长度不一定为1 对于发送消息来说 首先预置一个msgbuf缓冲区并写入消息类型和内容 调用相应的发送函数即可 对读取消息来说 首先分配这样一个msgbuf缓冲区 然后把消息读入该缓冲区即可3 获得或设置消息队列属性 消息队列API共有四个 使用时需要包括几个头文件 include include include 74 消息队列的基本操作 msgget 功能创建一个新消息队列或打开一个存在的队列函数原型intmsgget key tkey intflag 参数说明key 待创建 打开队列的键值 如果key值为IPC PRIVATE则创建一个新的消息队列 flag 创建 打开方式IPC CREAT 如果存在与当前key值相同的消息队列 则返回该消息队列id 如果不存在 则创建一个新的消息队列 IPC EXCL 如果存在与当前key值相同的消息队列 则返回失败 返回值成功返回消息队列描述符 否则返回 1 ftok函数 ftok原型 key tftok char fname intid 参数 fname指定的文件名 该文件必须是存在而且可以访问的 id是子序号 虽然为int 但是只有8个比特被使用 0 255 返回值 当成功执行的时候 一个key t值将会被返回 否则 1被返回 在一般的UNIX实现中 是将文件的索引节点号取出 前面加上子序号得到key t的返回值 如指定文件的索引节点号为65538 换算成16进制为0 x010002 而你指定的ID值为38 换算成16进制为0 x26 则最后的key t返回值为0 x26010002 76 消息队列的基本操作 msgrcv 函数原型ssize tmsgrcv intmsqid structmsgbuf msgp size tsize longtype intflag 功能该系统调用从msqid代表的消息队列中读取一个消息 并把消息存储在msgp指向的msgbuf结构中 参数说明msqid 消息队列描述字 描述从哪个消息队列读取消息msgp 消息存储位置size 消息内容的长度 mtext type 请求读取的消息类型根据type的不同分成三种情况处理type 0 接收该队列的第一个消息 并将它返回给调用者type 0 接收类型type的第一个消息type 0 接收小于等于type绝对值的最低类型的第一个消息 77 消息队列的基本操作 msgrcv 工作流程 flag 规定队列无消息时内核应做的操作IPC NOWAIT 如果现在没有消息 调用进程立即返回 同时返回 1 IPC EXCEPT type 0时使用 返回第一个类型不为type的消息IPC NOERROR 如果队列中满足条件的消息内容大于所请求的size字节 则把该消息截断 截断部分将丢失 如果没有设置IPC NOERROR 而消息又太长 则出错返回E2BIG 此时消息仍留在队列中 调用返回 成功返回读出消息的实际字节数 否则返回 1 注意 取消息的时候并不一定按照先进先出的次序取消息 可以按照消息的类型字段取消息 78 函数原型intmsgsnd intmsqid structmsgbuf msgp size tmsgsize intflag 功能向msqid代表的消息队列发送一个消息 即将发送的消息存储在msgp指向的msgbuf结构中 消息的大小由msgze指定 参数说明对发送消息来说 有意义的flag标志为IPC NOWAIT 指明在消息队列没有足够空间容纳要发送的消息时 msgsnd是否等待 造成msgsnd 等待的条件 当前消息的大小与当前消息队列中的字节数之和超过了消息队列的总容量 msgsnd 解除阻塞的条件有三个 消息队列中有容纳该消息的空间 msqid代表的消息队列被删除 调用msgsnd 的进程被信号中断 调用返回 成功返回0 否则返回 1 消息队列的基本操作 msgsnd 79 消息队列的基本操作 msgctl 函数原型intmsgctl intmsqid intcmd structmsqid ds buf 功能该系统调用对由msqid标识的消息队列执行cmd操作 共有三种cmd操作 IPC STAT IPC SET IPC RMID IPC STAT 该命令用来获取消息队列信息 返回的信息存贮在buf指向的内存中 IPC SET 该命令用来设置消息队列的属性 要设置的属性存储在buf指向的msqid ds结构中 可设置属性包括 msg perm uid msg perm gid msg perm mode以及msg qbytes IPC RMID 删除msqid标识的消息队列 调用返回 成功返回0 否则返回 1 include include include include include includestructmsg longmsg types charmsg buf 512 intmain intqid intpid intlen structmsgpmsg pmsg msg types getpid sprintf pmsg msg buf hello thisis d n getpid len strlen pmsg msg buf key tkey key ftok usr local test 30 if qid msgget 0 x66 IPC CREAT 0666 0 perror msgget exit 1 if msgsnd qid include include include include include defineBUFSIZE4096structmsg longmsg types charmsg buf 511 intmain intargc char argv intqid len structmsgpmsg qid msgget 0 x66 IPC CREAT 0666 key tkey key ftok usr local test 30 len msgrcv qid 82 消息队列使用示例 发送 include include include include include includestructmsg longmsg types charmsg buf 512 intmain intqid intpid intlen structmsgpmsg pmsg msg types getpid sprintf pmsg msg buf hello thisis d n getpid len strlen pmsg msg buf if qid msgget IPC PRIVATE IPC CREAT 0666 0 perror msgget exit 1 if msgsnd qid 83 消息队列使用示例 接收 include include include

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论