当前位置: 首页 > news >正文

Linux下的软件编程——IPC机制(信号和共享内存)

信号

1.信号:

            实现进程间的通知机制

           实现进程间的异步通信

           软中断

异步通信:接收方不知道什么时候发送方会发送数据

1.系统支持的信号

   kill -l               

2)SIGINT:ctrl+c        让一个进程被打断

3)SIGQUIT:ctrl+\        让一个进程结束

9)SIGKILL:        强制让一个进程结束

11)SIGSEGV:        让一个进程结束(段错误)

13)SIGPIPE:        让一个进程结束(管道破裂)

14)SIGALRM:        让一个进程结束(定时时间到达)

17)SIGCHLD:        子进程结束时发送给父进程

18)SIGCONT:        让停止态的进程继续执行

19)SIGSTOP:        让运行态的进程进入暂停态(暂停)强制停止

20)SIGTSTP:ctrl + z        让进程进入暂停态,后台进程,来自终端的停止信号

10)SIGUSR1  12)SIGUSR2        用户可自定义的信号

9)SIGKILL  19)SIGSTOP        管理员信号:只能按照默认方式处理,不能被忽略和捕获

2.信号处理流程

当进程收到一个信号,会打断该进程正在执行的任务,处理信号产生的事件;

当该事件处理完时,进程又从原来的位置继续执行

signal:注册一个信号

typedef  void  (*sighandler_t)(int)

sighandler_t  signal(int signum,sighandler_t handler)

(1)功能:设置信号的处理方式(注册一个信号)

(2)参数:signum:要处理的信号的编号

                    handler:SIG_IGN:以忽略方式处理该信号(不处理)

                                    SIG_DFL:以缺省的方式处理(系统默认方式)

                                    函数的地址:以捕获方式处理(自定义)

(3)返回值:失败:NULL        自定义方式:返回自定义的函数入口

void(*sighandler_t)(int signum)

sighandler_t:执行信号任务处理函数的入口

参数:signum:触发该任务函数的信号            

注意:1.若信号不被注册,则按照默认方式处理

           2.信号只需注册一次即可

           3.每次信号的到来都会触发一次信号任务处理函数

           4.信号尽可能早注册

#include <stdio.h>
#include <signal.h>void handler(int signum)
{printf("%d signal comming\n", signum);
}int main(int argc, const char *argv[])
{signal(SIGINT, SIG_IGN);
//	signal(SIGINT, SIG_DFL);//	signal(SIGKILL, handler);while (1){printf("hello world\n");sleep(1);}return 0;
}

3.发送信号               

1)kill命令

2)kill()

int kill(pid_t pid,int sig)

(1)功能:给指定的进程发送一个信号

(2)参数:pid:接收信号的进程PID

                    sig:信号的编号

(3)返回值:成功:0        失败:-1

void handler(int signum)
{int i = 3;while(i--){printf("Son is doing homework\n");sleep(1);}
//	kill(getppid(), SIGUSR2);exit(0);
}void handler2(int signum)
{printf("%d signal is comming\n", signum);wait(NULL);exit(0);
}int main(int argc, const char *argv[])
{pid_t pid = fork();if (pid > 0){signal(SIGCHLD, handler2);int i = 8;while (i--){printf("Father is working\n");sleep(1);}kill(pid, SIGUSR1);while (1){printf("xxxxxxxxxxxx\n");sleep(1);}}else if (0 == pid){signal(SIGUSR1, handler);while (1){printf("Son is playing games\n");sleep(1);}}else {perror("fork error");}return 0;
}

3)子进程结束时,会发送SIGCHLD信号给父进程

      子进程空间异步回收:通过子进程发送的SIGCHLD信号实现

4)int  raise(int sig)

给自己所在进程发送信号

5)unsigned int alarm(unsigned int seconds)

(1)功能:设置一个闹钟,当闹钟时间到达时,向自己所在的进程发送一个SIGALRM的信号

(2)参数:seconds:设置的闹钟的定时时间

(3)返回值:成功返回上次设定剩余的时间        上次未设定则返回0

#include "head.h"void handler(int signum)
{printf("%d signal comming\n", signum);alarm(5);
}int main(int argc, const char *argv[])
{signal(SIGALRM, handler);unsigned int cnt = alarm(5);while (1){printf("hello world\n");sleep(1);}return 0;
}

6)pause()

功能:让进程挂起(进入到睡眠状态)             

#include "head.h"void handler(int signo)
{}int main(int argc, const char *argv[])
{signal(SIGINT, handler);pause();while (1){printf("hello world\n");sleep(1);}return 0;
}

注意:1.pause可以被一个信号唤醒

           2.这个信号必须要被捕获

4.共享内存

共享内存:进程间效率最高的通信方式

1)通信原理

使用内核空间中的内存区域共享数据

使用内存映射技术,减少的数据的反复拷贝,提高了通信效率

2)共享内存操作流程

IPC对象

1*创建一个IPC key:

key_t  ftok(const char *pathname,int proj_id) 

(1)功能:创建一个IPC key

(2)参数:pathname:路径

                    proj_id:工程ID       

注意:两个进程创建KEY时必须使用相同的参数

(3)返回值:成功:IPC key         失败:-1    

2*创建共享内存

int  shmget(key_t key,size_t size,int shmflg)

(1)功能:创建一个共享内存

(2)参数:key:IPC key

                    size:共享内存大小

                              会被扩展成PAGE_SIZE(4096字节)的整数倍

                    shmflg:IPC_CREAT | 0664

(3)返回值:成功:返回一个共享内存ID        失败:返回-1

3*建立共享内存段和用户空间的内存映射

void *shmat(int shmid,const void *shmaddr,int shmflg)

(1)功能:建立共享内存内存映射

(2)参数:shmid:共享内存大小

                    shmaddr:映射的用户空间首地址

                                     NULL:让操作系统分配

                    shmflg:SHM_RDONLY  只读

                                  !SHM_RDONLY  读写

(3)返回值:成功:映射空间首地址        失败:(void*)-1

4*想共享内存写入数据——>通过用户空间的首地址

5*解除映射关系

int shmdt(const void*shmaddr)

(1)功能:解除内存映射关系

(2)参数:shmaddr:要接触的用户空间首地址

(3)返回值:成功:0        失败:-1

6*删除共享内存

int shmctl(int shmid,int cmd,struct shmid_ds *buf)

(1)功能:操作共享内存

(2)参数:shmid:要操作的共享内存id

                    cmd:要执行的操作指令

                              IPC_PMID  删除操作

                    buf:设置的参数

ipcs -a        查看内核中的IPC对象

ipcrm -s        删除信号量集

ipcrm -m        删除共享内存

ipcrm -m shmid

ipcrm -M shmkey

发送

int main(int argc, const char *argv[])
{//ftok();//shmget();//shmat();//p-->//shmdt();//shmctl();key_t key = ftok(".", '!');if (key < 0){perror("ftok error");return -1;}printf("key = %x\n", key);int shmid = shmget(key, 4096,IPC_CREAT|0664);if (shmid < 0){perror("shmget error");return -1;}printf("shmid = %d\n", shmid);void *pmem = shmat(shmid, NULL, !SHM_RDONLY);if ((void *)-1 == pmem){perror("shmat error");return -1;}//*((int *)pmem) = 10;strcpy((char *)pmem, "hello");shmdt(pmem);//shmctl(shmid, IPC_RMID, NULL);return 0;
}

接收

int main(int argc, const char *argv[])
{//ftok();//shmget();//shmat();//p-->//shmdt();//shmctl();key_t key = ftok(".", '!');if (key < 0){perror("ftok error");return -1;}printf("key = %x\n", key);int shmid = shmget(key, 4096, IPC_CREAT|0664);if (shmid < 0){perror("shmget error");return -1;}printf("shmid = %d\n", shmid);void *pmem = shmat(shmid, NULL, !SHM_RDONLY);if ((void *)-1 == pmem){perror("shmat error");return -1;}printf("recv: %s\n", (char *)pmem);	shmdt(pmem);//shmctl(shmid, IPC_RMID, NULL);return 0;
}

5.信号量集

实现进程间同步

6.消息队列

和管道类似,有同步效果

增加数据的等级(优先级:优先级数据越小,优先级越高)

                                        

     

http://www.dtcms.com/a/339619.html

相关文章:

  • QT6(常用界面组件的使用和布局管理)
  • 芯片没有型号能解密程序么?
  • 多线程—飞机大战排行榜功能(2.0版本)
  • 量化交易 - 概念板块对应股票 python代码
  • IEEE Transactions on Communications (TCOM) 投稿状态记录
  • 右值引用与移动语义【C++进阶每日一学】
  • Chrome插件开发【windows】
  • Infusing fine-grained visual knowledge to Vision-Language Models
  • Kotlin 协程之Channel
  • Python脚本每天爬取微博热搜-升级版
  • 电商数据分析可视化预测系统
  • GPT-5论文写作全流程提示词库
  • 点大餐饮独立版系统源码v1.0.3+uniapp前端+搭建教程
  • 图像采集卡与工业相机:机器视觉“双剑合璧”的效能解析
  • spring事务(@Transactional)失效的情景及处理
  • RabbitMQ:SpringAMQP 多消费者绑定同一队列
  • shenyu网关与与nacos业务网关的定位
  • 源网荷储 + 微电网:1+1 如何大于 2?能源协同解决方案
  • c++日志宏 INFO(...)
  • Webpack 5 配置完全指南:从入门到精通
  • Docker镜像--镜像分层、UnionFS、镜像发布、私有库Registry
  • Java -- 用户线程和守护线程--线程同步机制
  • 大模型问题:幻觉分类+原因+各个训练阶段产生幻觉+幻觉的检测和评估基准
  • OpenSCA开源社区每日安全漏洞及投毒情报资讯|18th Aug. , 2025
  • 【GNSS定位原理及算法杂记6】​​​​​​PPP(精密单点定位)原理,RTK/PPK/PPP区别讨论
  • usb通信中工作模式:主机模式和设备模式
  • 2025年渗透测试面试题总结-21(题目+回答)
  • 水闸安全监测的主要核心内容
  • Java NIO 核心精讲(上):Channel、Buffer、Selector 详解与 ByteBuffer 完全指南
  • 数字政务安全实战:等保2.0下OA系统的身份认证与数据防护