免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2154 | 回复: 7
打印 上一主题 下一主题

关于apue2中利用信号实现同步的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-09-24 15:00 |只看该作者 |倒序浏览
原始程序清单:
程序清单10-17
tellwait.c

#include "apue.h"
static volatile sig_atomic_t sigflag;
        /* set nonzero by signal handler */
static sigset_t   newmask, oldmask, zeromask;
static void
sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */
{
sigflag = 1;
return;
}
void
TELL_WAIT()
{
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
  err_sys("signal(SIGINT) error");
if (signal(SIGUSR2, sig_usr) == SIG_ERR)
  err_sys("signal(SIGQUIT) error");
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)
  err_sys("SIG_BLOCK error");
}
void
TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2);  /* tell parent we're done */
}
void
WAIT_PARENT(void)
{
while (sigflag == 0)
  sigsuspend(&zeromask); /* and wait for parent */
sigflag = 0;
   /* reset signal mask to original value */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
  err_sys("SIG_SETMASK error");
}
void
TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR1);   /* tell child we're done */
}
void
WAIT_CHILD(void)
{
while (sigflag == 0)
  sigsuspend(&zeromask); /* and wait for child */
sigflag = 0;
   /* reset signal mask to original value */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
  err_sys("SIG_SETMASK error");
}

所执行的程序清单:
#include "apue.h"
static void charatatime(char *);
int
main(void)
{
pid_t pid;
TELL_WAIT();
if ((pid = fork()) < 0) {
  perror("fork error");
} else if (pid == 0) {
  WAIT_PARENT();  /* parent goes first */
  charatatime("output from child\n");
  TELL_PARENT(getppid());
  WAIT_PARENT();  /* parent goes first */
  charatatime("11111111111111111111111111111111111111111111111111\n");
  TELL_PARENT(getppid());
} else {
  charatatime("output from parent\n");
  TELL_CHILD(pid);
  WAIT_CHILD();
  charatatime("22222222222222222222222222222222222222222222222222\n");
  TELL_CHILD(pid);
  WAIT_CHILD();
}
exit(0);
}
static void
charatatime(char *str)
{
char *ptr;
int  c;
setbuf(stdout, NULL);   /* set unbuffered */
for (ptr = str; (c = *ptr++) != 0; )
  putc(c, stdout);
}

程序运行结果:
./tellwait2;./tellwait2;./tellwait2
output from parent
output from child
22222222222222222222222222222222222222222222222222
11111111111111111111111111111111111111111111111111
output from parent
output from child
22222222222222222222222222222222222222222222222222
11111111111111111111111111111111111111111111111111
output from parent
output from child
22222222222222222222222222222222222222222222222222
11111111111111111111111111111111111111111111111111
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
我想不通两个地方
1.为什么要用SIGUSR1 SIGUSR2两个信号? (感觉只用一个信号就行了)
2.为什么要在TELL_WAIT中通过sigprocmask阻塞这两个信号?(感觉不阻塞也行)
所以我将代码改成下面的:
程序清单10-17
tellwait.c(修改)
#include "tellwait.h"
static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
static sigset_t newmask, oldmask, zeromask;
static void
sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */
{
sigflag = 1;
}
void
TELL_WAIT(void)
{
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
  perror("signal(SIGUSR1) error");
}
void
TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR1);  /* tell parent we're done */
}
void
WAIT_PARENT(void)
{
while (sigflag == 0)
  sigsuspend(&zeromask); /* and wait for parent */
sigflag = 0;
}
void
TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR1);   /* tell child we're done */
}
void
WAIT_CHILD(void)
{
while (sigflag == 0)
  sigsuspend(&zeromask); /* and wait for child */
sigflag = 0;
}
所执行的程序清单与原先的程序清单相同)
#include "tellwait.h"
static void charatatime(char *);
int
main(void)
{
pid_t pid;
TELL_WAIT();
if ((pid = fork()) < 0) {
  perror("fork error");
} else if (pid == 0) {
  WAIT_PARENT();  /* parent goes first */
  charatatime("output from child\n");
  TELL_PARENT(getppid());
  WAIT_PARENT();  /* parent goes first */
  charatatime("11111111111111111111111111111111111111111111111111\n");
  TELL_PARENT(getppid());
} else {
  charatatime("output from parent\n");
  TELL_CHILD(pid);
  WAIT_CHILD();
  charatatime("22222222222222222222222222222222222222222222222222\n");
  TELL_CHILD(pid);
  WAIT_CHILD();
}
exit(0);
}
static void
charatatime(char *str)
{
char *ptr;
int  c;
setbuf(stdout, NULL);   /* set unbuffered */
for (ptr = str; (c = *ptr++) != 0; )
  putc(c, stdout);
}
执行结果与原执行结果一样)
程序运行结果:
./a.out;./a.out;./a.out
output from parent
output from child
22222222222222222222222222222222222222222222222222
11111111111111111111111111111111111111111111111111
output from parent
output from child
22222222222222222222222222222222222222222222222222
11111111111111111111111111111111111111111111111111
output from parent
output from child
22222222222222222222222222222222222222222222222222
11111111111111111111111111111111111111111111111111


请教下我修改的程序哪些地方会出错~~~

附件为我修改的程序~

[ 本帖最后由 zxkevin 于 2007-9-24 16:01 编辑 ]

testtellwait2.rar

4.17 KB, 下载次数: 38

论坛徽章:
0
2 [报告]
发表于 2007-09-24 15:48 |只看该作者
用code把代码框起来吧

论坛徽章:
0
3 [报告]
发表于 2007-09-24 16:02 |只看该作者
恩~~~

论坛徽章:
0
4 [报告]
发表于 2007-09-24 16:27 |只看该作者
对于第一个问题,我觉得用一个信号也是可以的,本来作者也没说一定要两个
至于第二个问题,我觉得是这样的
void
WAIT_PARENT(void)
{
while (sigflag == 0)            # 1
  sigsuspend(&zeromask); /* and wait for parent */   #2
在#1和#2之间有个时间窗口,基于楼住修改后的情况,如果在这个时间窗口内,父进程发送一个信号给子进程,子进程从信号处理程序执行并返回,之后如果调用sigsuspend的话,程序就会一直阻塞,父子进程形成死锁。

论坛徽章:
0
5 [报告]
发表于 2007-09-24 16:37 |只看该作者
恩,明白了~~
zwylinux 太感谢您了~~ 哈哈

论坛徽章:
0
6 [报告]
发表于 2007-09-24 16:56 |只看该作者
还有个问题,您看下我这样分析对不对哈:

在没有被修改过的代码tellwait.c里,在WAIT_PARENT, WAIT_CHILD中都使用了sigprocmask恢复原先的信号集. 若像这样,在所执行的程序清单里的主进程只能有1个WAIT_CHILD,同理,在子进程中也只能有一个WAIT_PARENT了!因为sigprocmask已经恢复了以前的信号集了,而原先的信号集并没有阻塞SIGUSR1 SIGUSR2....若在主进程中有两个以上的WAIT_CHILD就会出现您所说的那种情况,造成死锁!子进程中若有两个以上的WAIT_PARENT也会造成死锁!~

论坛徽章:
0
7 [报告]
发表于 2007-09-24 17:12 |只看该作者
应该是这样的

论坛徽章:
0
8 [报告]
发表于 2007-09-24 17:13 |只看该作者
呵呵,谢谢~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP