LINUX进程间的通信(IPC)--信号
创始人
2024-09-25 18:27:57
0

一、概念

信号通信,其实就是内核向用户空间进程发送信号,只有内核才能发信号,用户空间进程不能发送信号。信号已经是存在内核中的了,不需要用户自己创建。

信号通信的框架         * 信号的发送(发送信号进程):kill、raise、alarm         * 信号的接收(接收信号进程) : pause()、 sleep、 while(1)         * 信号的处理(接收信号进程) :signal

二、相关函数

1.信号的发送(发送信号进程)

所需头文件: #include #include 函数原型:int kill(pid_t pid, int sig); 参数: 函数传入值:pid         正数:要接收信号的进程的进程号         0:信号被发送到所有和pid进程在同一个进程组的进程         ‐1:信号发给所有的进程表中的进程(除了进程号最大的进程外) sig:信号 函数返回值:成功 0 出错 ‐1示例:
#include  #include  #include  #include    int main(int argc,char *argv[]) {         int pid,sig;         if(argc != 3)         {                 printf("输入错误\n");                 return -1;         }         sig = atoi(argv[1]);         pid = atoi(argv[2]);          printf("pid = %d,sig = %d\n",pid,sig);          int rnt = kill(pid,sig);         if(rnt == 0)         {                 printf("杀死进程%d成功\n",pid);         }          return 0; } ~   
运行结果:

2.raise: 发信号给自己 == kill(getpid(), sig)

所需头文件: #include #include 函数原型: int raise(int sig); 参数: 函数传入值:sig:信号 函数返回值: 成功 0 出错 ‐1示例:
#include  #include  #include  #include   int main() {         printf("hello;\n");           //int rnt = raise(9);         int rnt = kill(getpid(),9);         if(rnt == 0)         {                 printf("杀死自己成功\n");         }          printf("world\n");         return 0; } 

运行结果:

3.alarm : 发送闹钟信号的函数

alarm 与 raise 函数的比较:         相同点:让内核发送信号给当前进程         不同点:                 alarm 只会发送SIGALARM信号                 alarm 会让内核定时一段时间之后发送信号, raise会让内核立刻发信号 所需头文件#include 函数原型 unsigned int alarm(unsigned int seconds) 参数: seconds:指定秒数 返回值:         成功:如果调用此alarm()前,进程中已经设置了闹钟时间,则 返回上一个闹钟时间的剩余时间,否则返回0。         出错:‐1示例:
#include  #include  #include   int main() { 	int i; 	alarm(5); 	printf("alarm start\n"); 	for(i =0 ;i<20;i++) 	{ 		sleep(1); 		printf("i = %d\n",i); 	}  	return 0; } 

运行结果:

4.信号的接收

接收信号的进程,要有什么条件:要想使接收的进程能收到信号,这个进程不能结束 : sleep        pause:进程状态为S (休眠)函数原型 int pause(void); 函数返回值:成功:0,出错:‐1示例:
#include  #include  #include   int main() {         int i,rnt;         printf("pause start\n");         pause();         for(i =0 ;i<20;i++)         {                 sleep(1);                 printf("i = %d\n",i);         }         return 0; } 

运行结果:

5.信号的处理

收到信号的进程,应该怎样处理? 处理的方式:         1.进程的默认处理方式(内核为用户进程设置的默认处理方式)                 A:忽略B:终止进程C: 暂停         2.自己的处理方式:                 自己处理信号的方法告诉内核,这样你的进程收到了这个信号就会采用你自己的的处理方式、 函数原型 void (*signal(int signum, void (*handler)(int)))(int); 参数:signum指定信号 handler:        1.SIG_IGN:忽略该信号。         2.SIG_DFL:采用系统默认方式处理信号        3.自定义的信号处理函数指针 函数返回值 成功:设置之前的信号处理方式 出错:‐1 signal 函数有二个参数,第一个参数是一个整形变量(信号值),第二个参数是一个函数指针,是我们自己写的处理函 数;这个函数的返回值是一个函数指针。

1.示例:自定义的信号处理函数指针

#include  #include  #include  void myfun(int signum) {         int i;         while(i<5)         {                 printf("signum = %d,i = %d\n",signum,i);                 i++;                 sleep(1);         } } int main() {         int i,rnt;         signal(14,myfun);//14信号是定时器到时发出         printf("alarm start\n");         alarm(7);         for(i =0 ;i<10;i++)         {                 sleep(1);                 printf("i = %d\n",i);         }         return 0; } 

运行结果:PS:回调函数执行完之后会重新回到主函数继续执行

2.示例:忽略该信号

#include  #include  #include  void myfun(int signum) { 	int i; 	while(i<5) 	{ 		printf("signum = %d,i = %d\n",signum,i); 		i++; 		sleep(1); 	} } int main() { 	int i,rnt; 	signal(14,myfun);//14信号是定时器到时发出 	printf("alarm start\n"); 	alarm(7);  	signal(14,SIG_IGN); 	for(i =0 ;i<10;i++) 	{ 		sleep(1); 		printf("i = %d\n",i); 	} 	return 0; } 

运行结果:

3.示例:采用系统默认方式处理信号

#include  #include  #include  void myfun(int signum) { 	int i; 	while(i<5) 	{ 		printf("signum = %d,i = %d\n",signum,i); 		i++; 		sleep(1); 	} } int main() { 	int i,rnt; 	signal(14,SIG_DFL); 	printf("alarm start\n"); 	alarm(7); 	for(i =0 ;i<10;i++) 	{ 		sleep(1); 		printf("i = %d\n",i); 	} 	return 0; } 

运行结果:

三、信号灯

信号灯集合(可以包含多个信号灯)IPC对象是一个信号的集合(多个信号量) , 一个信号灯有多个信号量。

1.相关函数

1.函数原型: int semget(key_t key, int nsems, int semflg);

功能:创建一个新的信号量或获取一个已经存在的信号量的键值。 函数参数: key和信号灯集关联的key值 nsems: 信号灯集中包含的信号灯数目 semflg信号灯集的访问权限 函数返回值: 成功:信号灯集ID 出错:‐1示例:
#include #include  #include  #include  #include  int main() { 	int semID; 	semID = semget(IPC_PRIVATE,3,0755); 	if(semID == -1) 	{ 		printf("信号灯创建失败\n"); 		perror("semget:"); 		return -1; 	} 	else 	{ 		printf("信号灯创建成功,semID = %d\n",semID); 	} 	system("ipcs -s");//查看信号灯信息 	return 0; } 

运行结果:

2.函数原型:int semctl ( int semid, int semnum, int cmd,…union semun arg(不是地址));

功能:控制信号量,删除信号量或初始化信号量 函数参数: semid:信号灯集ID semnum: 要修改的信号灯编号 cmd :         GETVAL:获取信号灯的值         SETVAL:设置信号灯的值         IPC_RMID:从系统中删除信号灯集合 函数返回值: 成功:0 出错:‐1 示例:
#include #include  #include  #include  #include  int main() {         int semID;         semID = semget(IPC_PRIVATE,3,0755);         if(semID == -1)         {                 printf("信号灯创建失败\n");                 perror("semget:");                 return -1;         }         else         {                 printf("信号灯创建成功,semID = %d\n",semID);         }         system("ipcs -s");//查看信号灯信息          semctl(semID,1,IPC_RMID,NULL);         printf("删除过后的信号灯\n");         system("ipcs -s");          return 0; } ~      

运行结果:

三、PV操作

int semop(int semid ,struct sembuf *sops ,size_t nsops); 功能:用户改变信号量的值。也就是使用资源还是释放资源使用权 参数: semid : 信号量的标识码。也就是semget()的返回值 sops是一个指向结构体数组的指针。         struct sembuf{         unsigned short sem_num;   //信号灯编号;         short sem_op;                        //对该信号量的操作。‐1 ,P操作,1 ,V操作         short sem_flg;                        //0阻塞,1非阻塞         }; sem_op : 操作信号灯的个数 //如果其值为正数,该值会加到现有的信号内含值中。通常用于释放所控资源的使用权;如果sem_op的值为负 数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值。通常用于获取资源的使用 权;如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。 示例:
#include  #include  #include  #include  #include  #include   #define SEM_READ 0 #define SEM_WRITE 0 union semun {         int val; };   void pfuntion(int id,int index) {         struct sembuf sem;         sem.sem_num = index;         sem.sem_op = -1;         sem.sem_flg = 0;          semop(id,&sem,1); }   void vfuntion(int id,int index) {         struct sembuf sem;         sem.sem_num = index;         sem.sem_op = 1;         sem.sem_flg = 0;          semop(id,&sem,1); }  int main()  {         key_t key;         pid_t pid;         int shmid,semid;         char *shmaddr;         key = ftok("a.c",1);         semid = semget(key,2,IPC_CREAT|0755);//创建信号灯         if(semid == -1)         {                 perror("semget");                 return -1;         }          shmid = shmget(key,128,IPC_CREAT|0755);//创建共享内存         if(shmid == -1)         {                 perror("shmget");                 return -2;         }         //初始化信号灯         union semun mynu;         //初始化读         mynu.val = 0;//读的信号灯值         semctl(semid,SEM_READ,SETVAL,mynu);          //初始化写         mynu.val = 1;//写的信号灯值         semctl(semid,SEM_WRITE,SETVAL,mynu);          pid = fork();         if(pid == -1)         {                 perror("fork");                 return -3;         }        if(pid > 0)         {                 printf("这是一个父进程\n");                 while(1)                 {                         shmaddr = (char *)shmat(shmid,NULL,0);                         pfuntion(semid,SEM_READ);                         printf("父进程请输入数据:");                         fgets(shmaddr,32,stdin);                         vfuntion(semid,SEM_WRITE);                 }         }          if(pid == 0)         {                 printf("这是一个子进程\n");                 while(1)                 {                         shmaddr = (char *)shmat(shmid,NULL,0);                         pfuntion(semid,SEM_READ);                         printf("子进程读取到的数据是:%s\n",shmaddr);                         vfuntion(semid,SEM_WRITE);                  }         }         return 0; }                                             

运行结果:

相关内容

热门资讯

安卓系统为什么不封闭,揭秘安卓... 你有没有想过,为什么安卓系统那么开放,却不像苹果iOS那样封闭呢?这背后可是有着不少有趣的故事和原因...
安卓系统更新包多大,解析不同版... 你有没有发现,每次安卓系统更新,手机里都会多出那么几个G的文件?这可真是让人好奇,安卓系统更新包究竟...
安卓手机安装双系统吗,安卓手机... 你有没有想过,你的安卓手机是不是也能像电脑一样,装上两个系统,一个用来工作,一个用来娱乐?没错,这就...
oppo会升级安卓系统,畅享最... 你知道吗?最近有个大消息在手机圈里炸开了锅,那就是OPPO要升级安卓系统啦!这可不是什么小打小闹的更...
安卓系统上安装windows,... 你有没有想过,在安卓手机上安装Windows系统?听起来是不是有点不可思议?但你知道吗,这竟然是可能...
安卓系统怎么进运行框,安卓系统... 你有没有想过,你的安卓手机里有一个超级实用的功能,那就是运行框!它就像是一个小助手,帮你快速找到正在...
安卓系统电视无图像设置,安卓电... 你家的安卓系统电视突然没图像了?别急,让我来给你支个招,让你轻松解决这个问题!一、检查电源和连接线首...
安卓机建议升级系统吗,提升性能 你有没有发现,你的安卓手机最近有点儿慢吞吞的?是不是在犹豫要不要升级系统呢?别急,让我来给你好好分析...
升级不了安卓系统升级,探寻升级... 你有没有遇到过这种情况?手机里的安卓系统突然告诉你,它需要升级,但你左等右等,就是升不上去。这可真是...
备用安卓系统手机推荐,盘点热门... 你有没有想过,如果你的手机突然罢工了,你会怎么办?别担心,今天我就要给你安利几款备用安卓系统手机,让...
旧安卓系统ipad无法更新系统... 你有没有遇到过这种情况?你的旧安卓系统iPad突然告诉你,它无法更新系统了!是不是瞬间感觉心里有点小...
运行安卓6系统命令大全,全面掌... 你有没有想过,你的安卓手机里隐藏着无数强大的功能,只等着你去发现和探索呢?今天,就让我带你走进安卓6...
安卓系统简笔画教程下载,轻松绘... 你有没有想过,用简单的线条就能把复杂的安卓系统画出来?没错,就是那种一看就懂,一画就上手的感觉!今天...
华为如何鸿蒙转安卓系统,轻松实... 你知道吗?最近华为的大动作可是让整个科技圈都沸腾了!他们竟然把鸿蒙系统转到了安卓系统上,这可真是让人...
安卓10系统的问题,安卓10系... 你有没有发现,自从你的手机升级到安卓10系统后,好像有点不对劲呢?别急,让我来给你细细道来,看看安卓...
安卓系统苹果搞笑视频,苹果搞笑... 你知道吗?在互联网的世界里,搞笑视频可是个永恒的热门话题。尤其是那些结合了安卓系统和苹果手机的搞笑片...
卡片机改造安卓系统,探索改造之... 你有没有想过,那些曾经陪伴我们记录美好时光的卡片机,现在竟然也能焕发第二春呢?没错,就是那些小巧便携...
装安卓系统倒车出不来,智能科技... 你有没有遇到过这样的事情:手机装了个安卓系统,结果倒车的时候出不来啦?这可不是闹着玩的,简直让人抓狂...
定制安卓系统哪家好点儿,哪家服... 你有没有想过,手机系统就像是个人的衣服,每个人都需要找到最适合自己的那一款?今天,咱们就来聊聊定制安...
台电用回安卓系统吗,开启智能新... 最近有个话题在科技圈里炒得挺热的,那就是台电是不是要用回安卓系统了?你有没有想过,这个小小的决定背后...