Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4065992
  • 博文数量: 251
  • 博客积分: 11197
  • 博客等级: 上将
  • 技术积分: 6862
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-05 14:41
个人简介

@HUST张友东 work@taobao zyd_com@126.com

文章分类

全部博文(251)

文章存档

2014年(10)

2013年(20)

2012年(22)

2011年(74)

2010年(98)

2009年(27)

分类: LINUX

2010-06-24 15:51:16

 
/*
 * 使用信号实现父子进程之间的同步
 *
 * TELL_WAIT(): set things up for TELL_xxx & WAIT_xxx
 * TELL_PARENT():  tell parent we are done
 * WAIT_PARENT():  wait for parent
 * TELL_CHILD(): tell child we are done
 * WAIT_CHILD(): wait for child
 *
 * SIGUSR1: the signal parent sends to child
 * SIGUSR2: the signal child sends to parent
 */
 

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
 
static volatile sig_atomic_t sigflag;
static sigset_t newmask, oldmask, zeromask;
/* signal handler for SIGUSR1 and SIGUSR2 */
static void sig_usr(int signo)
{
 sigflag = 1;
 return;
}
void TELL_WAIT()
{
 if(signal(SIGUSR1, sig_usr) == SIG_ERR)
  printf("signal SIGUSR1 error\n");
 if(signal(SIGUSR2, sig_usr) == SIG_ERR)
  printf("signal SIGUSR2 error\n");
  
 sigemptyset(&zeromask);
 
 sigemptyset(&newmask);
 sigaddset(&newmask, SIGUSR1);
 sigaddset(&newmask, SIGUSR2);
 
 /* block SIGUSR1 and SIGUSR2, and save current signal mask */
 if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
  printf("SIG_BLOCK error\n");
}
void TELL_PARENT(pid_t pid)
{
 kill(pid, SIGUSR2); /* tell parent we are done */
}
void WAIT_PARENT()
{
 while(sigflag == 0)
  sigsuspend(&zeromask); /* wait for parent */
 
 sigflag = 0;
 
 /* reset signal mask */
 if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
  printf("SIG_SETMASK error\n");
}
void TELL_CHILD(pid_t pid)
{
 kill(pid, SIGUSR1);
}
void WAIT_CHILD()
{
 while(sigflag == 0)
  sigsuspend(&zeromask); /* wait for parent */
 
 sigflag = 0;
 
 /* reset signal mask */
 if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
  printf("SIG_SETMASK error\n");
}
void do_task(char *task_str)
{
 printf("%s\n", task_str);
}
/* parent goes first program */
int main()
{
 pid_t pid;
 
 TELL_WAIT();
 
 pid = fork();
 if(pid < 0) {
  printf("fork error\n");
 }
 else if(pid == 0) {
  WAIT_PARENT();
  do_task("child task\n");
 }
 else {
  do_task("parent task\n");
  TELL_CHILD(pid);
 }
 
 return 0;
}
/* child goes first program*/
int main()
{
 pid_t pid;
 
 TELL_WAIT();
 
 pid = fork();
 if(pid < 0) {
  printf("fork error\n");
 }
 else if(pid == 0) {
  do_task("child task\n");
  TELL_PARENT(getppid());
 }
 else {
  WAIT_CHILD();
  do_task("parent task\n");
 }
 
 return 0;
}

/*
 * 使用管道实现父子进程同步
 *
 * 父进程在调用TELL_CHILD 时经由上一个管道写一个字符p,子进程在
 * 调用TELL_PARENT时,经由下一个管道写一个字符c。相应的WAIT_XXX
 * 函数调用read读一个字符,没有读到字符时阻塞(睡眠等待)。
 *
 */

 

static int pfd1[2], pfd[2];

void TELL_WAIT()
{
    if(pipe(pfd1) < 0 || pipe(pfd2) < 0)
        printf("pipe error\n");
}

void TELL_PARENT(pid_t pid)
{
    if(write(pfd2[1], "c", 1) != 1)
        printf("write error\n");
}

void WAIT_PARENT()
{
    char c;
    if(read(pfd1[0], &c, 1) != 1)
        printf("read error\n");
    if(c != 'p')
        printf("WAIT_PARENT: incorrect data\n");
}

void TELL_CHILD(pid_t pid)
{
    if(write(pfd1[1], "p", 1) != 1)
        printf("write error\n");
}


void WAIT_CHILD()
{
    char c;
    if(read(pfd1[0], &c, 1) != 1)
        printf("read error\n");
    if(c != 'c')
        printf("WAIT_CHILD: incorrect data\n");
}


阅读(4847) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~