CSAPP:异常控制流课后作业:交互打印pid
编写程序,一个父进程p0,创建两个子进程p1和p2;要求只使用信号相关机制作为通信手段,让p1打印出p2的pid,p2打印出p1的pid
解题思路:
总体思路是父进程掌握p1和p2的信息,让父进程给p2发送p1的信息,给p1发送p2的信息。但是只能发信号,不能发整数,所以只能一位一位的发,把pid_t 拆成32位发送。用两个信号 SIGUSR1和SIGUSR2 分别代表该位是1和该位是0的信息发送,父进程每取了pid的一位就向子进程发送对应的信号,然后pause,子进程那边收到信号后会给父进程回一个信号,我这里用的是SIGCONT,父进程收到后pause解除,继续干活。。(如果不回信可能会因为异步导致信号被丢弃)
信息发送完了之后父进程发送SIGINT使子进程输出并终止就可以了
测试结果:
代码:
#include"csapp.h"
#include<signal.h>
#include<stdio.h>
#include<sys/types.h>
volatile int s1[8],s2[8];
volatile pid_t pid,p0,p1,p2;
volatile long ppid; //pid of the other process
volatile int cnt; //count the bits
void handler_usr1(int sig) // if one bit is 1 , SIGUSR1 sent
{
sigset_t mask,prev_mask;
Sigfillset(&mask);
Sigprocmask(SIG_BLOCK,&mask,&prev_mask);
ppid = (ppid | (1<<cnt));
cnt++;
Sigprocmask(SIG_SETMASK,&prev_mask,NULL);
Kill(p0,SIGCONT);
}
void handler_usr2(int sig) // if one bit is 0 , SIGUSR2 sent
{
sigset_t mask,prev_mask;
Sigfillset(&mask);
Sigprocmask(SIG_BLOCK,&mask,&prev_mask);
cnt++;
Sigprocmask(SIG_SETMASK,&prev_mask,NULL);
Kill(p0,SIGCONT);
}
void handler_sigint(int sig) //prints and exit
{
Sio_puts("process ");
Sio_putl(pid);
Sio_puts(" prints pid ");
Sio_putl(ppid);
Sio_puts("\n");
_exit(0);
}
void handler_sigcont(int sig) //send signal to father
{
;
}
int main()
{
sigset_t mask,prev_mask;
p0=getpid();
cnt=0;
ppid = 0;
Sio_puts("The father's pid is: ");
Sio_putl(p0);
Sio_puts("\n");
Signal(SIGUSR1,handler_usr1);
Signal(SIGINT,handler_sigint);
Signal(SIGUSR2,handler_usr2);
Signal(SIGCONT,handler_sigcont);
if((p1=fork())==0)
{
pid=getpid();
while(1)
;
}
if((p2=fork())==0)
{
pid=getpid();
while(1)
;
}
Sio_puts("p1 = ");
Sio_putl(p1);
Sio_puts("\n");
Sio_puts("p2 = ");
Sio_putl(p2);
Sio_puts("\n");
Sigfillset(&mask);
for(int i=0;i<=31;i++)
{
if((p1>>i)&1)
{
Kill(p2,SIGUSR1);
Pause(); //pause to wait children to update
}
else
{
Kill(p2,SIGUSR2);
Pause(); //pause to wait children to update
}
}
for(int i=0;i<=31;i++)
{
if((p2>>i)&1)
{
Kill(p1,SIGUSR1);
pause();
}
else
{
Kill(p1,SIGUSR2);
Pause();
}
}
Kill(p1,SIGINT); // process p1 prints and exits
Waitpid(-1,NULL,0);
Kill(p2,SIGINT); // process p2 prints and exits
Waitpid(-1,NULL,0);
Sio_puts("exit\n"); // main process exits
_exit(0);
}