05多進程間使用信號進行通信

#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>


#if 1
/*
要求:
	3、信號可靠信號不可靠信號相關
	編程程序,要去實現如下功能:
	父進程創建子進程1和子進程2、子進程1向子進程2發送可靠信號,
	並傳送額外數據爲子進程1的pid*2;
	子進程2接受可靠信號的值,併發送給父進程,父進程把接受的值
	進行打印。
	提示:用sigqueue和sigaction實現

分析:
	1因爲孩子1的pid和孩子2的pid全部在父進程中
	2父進程把孩子2的pid,發給孩子1
	3孩子1有了孩子2的pid,孩子1就可以給孩子2發送信號了。
	
	父--->子1---->子2---->父
*/

// kill -l 查看信號

int pidArray[10];//使用全局變量緩存子進程id

 void myhandle(int num, siginfo_t *st, void *p)
 {
 	//子進程1接收到了信號
 	if(num == SIGRTMIN+1)
 	{
 		printf("孩子1收到信號值:%d \n", st->si_value.sival_int);
 		//獲取到子進程2的pid
 		pidArray[1] = st->si_value.sival_int;
 	}
 	
 	//子進程2接收到了信號
 	if(num == SIGRTMIN+2)
 	{
 		//孩子2收到信號
		printf("孩子2收到信號,值:%d \n", st->si_value.sival_int);
		//子進程的pid * 2
		pidArray[3] = st->si_value.sival_int;
 		
 	}
 	
 	//父進程接收到了信號
 	if(num == SIGRTMIN+3)
 	{
 		//父進程接收到了信號
		printf("父進程收到信號,值:%d \n", st->si_value.sival_int);
		printf("父進程中的pid[0]:%d pid[1]:%d \n", pidArray[0], pidArray[1]);
 	}
 	
 }
int test()
{
	int i = 0;
	struct sigaction act;
	act.sa_sigaction = myhandle;
	act.sa_flags = SA_SIGINFO;//表示信號要傳輸信息
	
	if(sigaction(SIGRTMIN+1, &act, NULL) == -1){
		perror("func sigaction err");
		return -1;	
	}
	if(sigaction(SIGRTMIN+2, &act, NULL) == -1){
		perror("func sigaction err");
		return -1;	
	}
	if(sigaction(SIGRTMIN+3, &act, NULL) == -1){
		perror("func sigaction err");
		return -1;	
	}
	
	
	int pid = 0;
	//連續創建2 個子進程
	for (i = 0; i < 2; i++)
	{
		//父進程可以把所有孩子的id緩存下來
		pidArray[i] = pid = fork();
		if(pid == 0)
		{
			break;//如果是孩子,不參與fork	
		}
		else if (pid > 0) 
		{
			;
		}
		
	}
	
	
	
	//子進程1向子進程2發送 子進程1的pid*2
	if (pid == 0 && i == 0) 
	{
		printf("子進程1運行\n");
		printf("子進程1 sleep\n");
		//sleep是可中斷的睡眠,只要linux內核發信號,進程就會醒來
		printf("進程1 sleep 剩餘時間爲 %d\n",sleep(5));
		printf("子進程1sleep被打斷後,全局變量有值了,即子進程1拿到了子進程2的pid:%d\n",pidArray[1]);
		
		//添加額外數據
		union sigval mysigval;
		mysigval.sival_int = getpid()*2;
		printf("子進程1給進程2發送信號getpid()*2:%d  \n", getpid()*2);
		//向子進程2發送消息
		if(sigqueue(pidArray[1], SIGRTMIN+2, mysigval) < 0 )
		{
			perror("func sigqueue err");
			return -1;			
		}
		printf("子進程1給子進程2發完信號啦,即將退出........\n");
		exit(0);
	}
	
	//子進程2 向父進程發送信號
	
	if (pid == 0 && i == 1) 
	{
		printf("進程2 sleep 剩餘時間爲 %d\n",sleep(20));
		printf("子進程2睡眠醒來,開始發送信號\n");
		
		//添加額外數據
		union sigval mysigval;
		mysigval.sival_int = pidArray[3];
		printf("子進程2給父進程發送信號pidArray[3]:%d  \n", pidArray[3]);
		
		
		//子進程2向父進程發送消息
		if(sigqueue(getppid(), SIGRTMIN+3, mysigval) < 0 )
		{
			perror("func sigqueue err");
			return -1;			
		}
		printf("子進程2給父進程發完信號啦,即將退出........\n");
		exit(0);	
	}
    
    
    //父進程向子進程1發送子進程2的pid
	if (pid > 0) 
	{
		printf("父進程運行\n");
		//父進程給進程1發信號 把進程2的pid發過去
		
		//添加額外數據
		union sigval mysigval;
		mysigval.sival_int = pidArray[1];
		
		//向子進程1發送消息
		if(sigqueue(pidArray[0], SIGRTMIN+1, mysigval) < 0 )
		{
			perror("func sigqueue err");
			return -1;			
		}
		printf("父進程給子進程1發完信號啦........\n");
		
	}
	               
    sleep(2);
    int mypid = 0;
    //非阻塞等待所有的子進程退出
    while ((mypid = waitpid(-1, NULL, WNOHANG)) > 0 )
    {
    	 printf("子進程退出pid:%d \n", mypid);
    }
    printf("hello........\n");  
    return 0; 
          
}
#endif

在這裏插入圖片描述

進行單獨測試父子進程通信,並沒有出現以上問題

#if 0

void myhandle(int num, siginfo_t *st, void *p)
 {
 	//子進程1接收到了信號
 	if(num == SIGRTMIN+1)
 	{
 		printf("收到信號值:%d \n", st->si_value.sival_int);
 	}
 }

int  test()
{
	struct sigaction act;
	act.sa_sigaction = myhandle;
	act.sa_flags = SA_SIGINFO;//表示信號要傳輸信息
	
	if(sigaction(SIGRTMIN+1, &act, NULL) == -1){
		perror("func sigaction err");
		return -1;	
	}

	
	int pid = 0;
	pid = fork();
	
	//子進程給父進程發送信號
	if (pid == 0) 
	{
		//添加額外數據
		union sigval mysigval;
		mysigval.sival_int = 111;
		
		//向子進程1發送消息
		if(sigqueue(getppid(), SIGRTMIN+1, mysigval) < 0 )
		{
			perror("func sigqueue err");
			return -1;			
		}
		exit(0);
	}
	
	sleep(2);
    int mypid = 0;
    //非阻塞等待所有的子進程退出
    while ((mypid = waitpid(-1, NULL, WNOHANG)) > 0 )
    {
    	 printf("子進程退出pid:%d \n", mypid);
    }
    printf("hello........\n");        
    return 0; 
	
}
#endif

int main()
{
	test();
	return 0;
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章