资讯详情

资讯详情

IPC进程间通信:信号通信与共享内存

什么是信号通信和共享内存Linux 提供了多种进程间通信IPC机制其中**信号Signal和共享内存Shared Memory**是两种风格截然不同、却都非常常用的方式信号轻量、异步、只传递发生了什么适合做事件通知。共享内存零拷贝、高吞吐适合传递大量数据但需要自己解决同步问题。2. 信号通信2.1 什么是信号信号是内核向进程投递的一种异步事件通知本质是一个整数编号。进程收到信号后执行默认动作终止、忽略、暂停、继续注册自定义处理函数阻塞或解除阻塞某个信号。信号通信应用异步通信。 通知机制。 随机事件信号发送和接收的过程1根据需要(随机事件)发生信号。2.linux 接收到信号发生请求在pcb的链表中查找对应的pid号(1000),3.找到对应进程后使原来工作流程先暂停下执行pcb 中信号处理函数 对应下标的函数。(如果发送Linux系统下全部信号预览以下是常用的信号信号编号默认动作典型用途SIGINT2终止CtrlC 中断SIGTERM15终止优雅退出请求SIGKILL9终止强制杀死不可捕获SIGCHLD17忽略子进程状态变化SIGUSR110终止用户自定义SIGUSR212终止用户自定义注意 SIGKILL 和 SIGSTOP 无法被捕获、阻塞或忽略这是内核的硬性保证。系统中对信号的说明和相关默认处终端输入;man 7 signal信号相关函数发送与捕获信号发送信号最常用的是 kill()捕获信号用 signal1.发送信号int kill(pid_t pid, int sig);功能通过该函数可以给pid进程发送信号为sig的系统信号。参数pid 要接收信号的进程pidsig 当前程序要发送的信号编号 《 kill -l返回值成功 0失败 -12.捕获信号void ( *signal(int signum, void (*handler)(int)) ) (int);sighandler_t signal(int signum, sighandler_t handler);handler有二个宏表示SIG_DFL表示默认处理SIG_IGN表示忽略处理fun表示自定义处注意信号处理的几个坑处理函数要尽量短只做置标志位、写管道等异步信号安全async-signal-safe的操作不要在里面 printf、malloc。注意信号丢失标准信号不排队连续多次发送同一信号可能只处理一次。需要计数时用实时信号SIGRTMIN 起或改用其他 IPC。EINTR 处理被信号打断的系统调用可能返回 -1 且 errno EINTR需要重试。代码示例3. 共享内存为什么需要共享内存管道、消息队列、socket 都需要内核做一次数据拷贝发送方 → 内核缓冲区 → 接收方。数据量大时这次拷贝的开销非常可观。共享内存的思路是让两个进程的虚拟地址映射到同一块物理内存。写入方直接写读取方直接读中间没有拷贝是性能最高的 IPC 方式。代价是内核不帮你做同步。多个进程同时读写同一块内存会产生竞态必须配合信号量、互斥锁或原子操作来保护。1.函数调用的步骤key 》申请对象 》映射对象》读写对象 》撤销映射 》删除对象2.与管道对比1.对于读写进程而言 双方都可以读写2.没有读阻塞3.没有写阻塞。 共享内存需要和其他ipc (信号或 信号量集(同步操作))进行搭配使用4.是一个初级内存区域(像字符数组)5.不删除数据数据保持的6.相对来说共享内存空间可以自定义(4K *n ), 大空间内存共享函数key_t ftok(const char *pathname, int proj_id);功能通过该函数可以将pathname指定的路径用来以proj_id生成唯一的临时键值。参数pathname 路径名称》任意文件只要不会被删除重建即可。proj_id整形的数字一般用ASCII码的单字符表示与参数1的运算。返回值成功 返回唯一键值失败-1int shmget(key_t key, size_t size, int shmflg);功能使用唯一键值key向内核提出共享内存使用申请参数key 唯一键值size要申请的共享内存大小shmflg申请的共享内存访问权限八进制表示,如果是第一个申请则用IPC_CREAT相关命令如果要检测是否存在用IPC_EXCL返回值成功 返回共享内存id一般用shmid表示失败-1映射对象shmat()void *shmat(int shmid, const void *shmaddr, int shmflg);功能将指定shmid对应的共享内存映射到本地内存。参数shmid 要映射的本地内存shmaddr本地可用的地址如果不确定则用NULL表示由系统自动分配。shmflg0,表示读写,SHM_RDONLY只读返回值成功 返回映射的地址一般等于shmaddr失败 (void*)-1注意判断返回值不算-1对内存的读写操作memcpy(); //二进制对象strcpy(); //字符串对象撤销映射shmdtint shmdt(const void *shmaddr);功能将本地内存与共享内存断开映射关系。参数shmaddr 要断开的映射地址。返回值成功 0,失败 -1删除对象shmctlint shmctl(int shmid, int cmd, struct shmid_ds *buf);功能修改共享内存属性也可以删除指定的共享内存对象。参数shmid 要删除的共享内存对象cmd IPC_RMID删除对象的宏buff NULL表示只删除对象。返回值成功 0,失败 -1共享内存实现通信代码示例;1.读端2.写端Linux系统中查看共享内存的命令1.ipcs -a查询共享内存信号量集消息队列2.ipcrm -m删除共享内存ipcs-a注意**ipcrm -m与 代码内shmctl(shmid,IPC_RMID,NULL)**效果一致前者需要终端手动打删除标记可以通过命令查看到内存共享状态栏后者会等到最后一个进程执行 shmdt 解除挂载
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →