#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;
}