wait for another process implemented by signal
-----sig_wait_proc.h
#ifndef _SIG_WAIT_PROC_H
#define _SIG_WAIT_PROC_H
extern void init_wait();
extern void wait_proc();
extern void tell_proc(pid_t);
#endif /* _SIG_WAIT_PROC_H */
-----sig_wait_proc.c
/*
* wait for another process implemented by signal
* APUE-2e 程序清单10-17
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include "sig_wait_proc.h"
static volatile sig_atomic_t sigflag; /* 0 */
static sigset_t newmask, oldmask, zeromask;
static void sig_usr1(int signo)
{
sigflag = 1;
}
void init_wait()
{
if(signal(SIGUSR1, sig_usr1) == SIG_ERR)
{
printf("signal(SIGUSR1) error.\n");
exit(1);
}
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
/* Block SIGUSR1 and save current signal mask */
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
printf("sigprocmask error.\n");
exit(1);
}
}
void wait_proc()
{
while(sigflag == 0)
{
sigsuspend(&zeromask);
}
sigflag = 0;
/* Reset signal mask to original value */
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
printf("sigprocmask error.\n");
exit(1);
}
}
void tell_proc(pid_t pid)
{
kill(pid, SIGUSR1);
}
-----main.c
/*
* demonstrate the race condition between parent process and child process
* APUE-2e 程序清单8-7
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "sig_wait_proc.h"
/*
* We set the standard output unbuffered, so every character output generates a write.
* The goal in this example is to allow the kernel to switch between the two processes as often as possible to demonstrate the race condition.
*/
static void putchars(char *str)
{
char *pstr;
for(pstr = str; *pstr != 0; pstr++)
{
write(STDOUT_FILENO, pstr, 1);
sleep(1);
}
}
int main()
{
pid_t pid;
init_wait();
if( (pid = fork()) < 0 )
{
printf("fork error.\n");
exit(1);
}
else if(pid == 0) /* child */
{
wait_proc();
putchars("ccccc\n");
}
else /* parent */
{
putchars("ppppp\n");
tell_proc(pid);
}
exit(0);
}
-----compiling command
$ gcc -Wall sig_wait_proc.c main.c -o main