0

这个程序应该

父母只是无限期地等待任何孩子返回(提示,waitpid)。湾。孩子设置了两个信号处理程序(提示、信号)并进入睡眠状态 5 分钟。一世。第一个信号处理程序监听 USR1 信号,并在接收到它时: 1. 创建一个线程(提示,pthread_create)。一个。基本上,线程需要做的就是“打个招呼”并休眠 60 秒。ii. 第二个信号处理程序侦听 USR2 信号,并在接收到它时: 1. 销毁线程(提示,pthread_cancel)。

当这个程序接收到第一个创建线程的信号时,它输出“[thread] sleep for 1 m[thread] sleep for 1 minute”然后结束,它从不等待第二个信号,我做错了什么?

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

pthread_t thread;

void* temp()
{
    printf("[thread] hello professor\n");
    printf("[thread] sleeping for 1 minute\n");
    sleep(60);
}
void handle_USR1(int x)
{
    int s;
    printf("[signal] creating the thread\n");
    s = pthread_create(&thread, NULL, &temp, NULL);
}

void handle_USR2(int x)
{
    int s;
    printf("[signal] destroying the thread\n");
    s = pthread_cancel(thread);
}

int main(void)
{
    int status = 0;

    if(fork() != 0)
    {
     printf("[parent] waiting.....\n");
     waitpid(-1, &status, 0);
    }
    else
    {
     printf("[child] to create the thread: kill -USR1 %d\n", getpid());
     printf("[child] to end the thread: kill -USR2 %d\n", getpid());
     printf("[child] setting up signal handlers\n");

     signal(SIGUSR1, handle_USR1);
     signal(SIGUSR2, handle_USR2);

     printf("[child] waiting for signals\n");
     sleep(300);
    }
    return (0);
}
4

3 回答 3

1

正如查理伯恩斯所指出的,这两个进程最终都会因信号而退出,但原因不同。

孩子

在睡眠期间,子进程在系统调用中被阻塞(实际的系统调用是nanosleep,用于实现该sleep()功能)。当进程在系统调用中接收到信号时,会执行相应的信号处理程序,系统调用会返回错误,EINTR表示它已被中断,无法履行其职责。然后,您可以决定是否要重新启动系统调用。收到 SIGUSR1 后,子进程执行的 nanosleep 系统调用被中断,处理程序被执行,并且 sleep() 立即返回。注意man 3 sleep关于 sleep() 的返回值的说明:

Zero if the requested time has elapsed, or the number of seconds left to sleep, if the call was interrupted by a signal handler.

正确的方法是让孩子检查睡眠的返回值(剩余的睡眠秒数),然后在这段时间内再次睡眠。

家长

与 Charlie Burns 所指出的不同,父母中的 waitpid() 不会因为孩子收到信号而返回。由于孩子退出,它返回。如果孩子没有处理信号,它会因为孩子而返回,因此被它杀死(未处理的信号导致进程死亡)。您可以(并且应该)检查使用 WIFEXITED 宏及其同伴,如man 2 waitpid. 该手册页底部的示例非常好:

do {
   w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
   if (w == -1) {
       perror("waitpid");
       exit(EXIT_FAILURE);
   }

   if (WIFEXITED(status)) {
       printf("exited, status=%d\n", WEXITSTATUS(status));
   } else if (WIFSIGNALED(status)) {
       printf("killed by signal %d\n", WTERMSIG(status));
   } else if (WIFSTOPPED(status)) {
       printf("stopped by signal %d\n", WSTOPSIG(status));
   } else if (WIFCONTINUED(status)) {
       printf("continued\n");
   }
} while (!WIFEXITED(status) && !WIFSIGNALED(status));

基本上,这段代码所做的是等待子进程,直到它正常退出或由于未处理的信号而退出。在您的情况下,父母最好检查状态变量以确保 waitpid 由于它期望的事件(孩子退出)而不是其他原因而返回。

于 2013-10-17T03:39:31.113 回答
0

好的,我明白发生了什么。

当您发送信号时,如果没有通过掩码将其定向到特定线程,则进程中的任何线程都可以获取它。当 SIGUSR1main在子进程中被传递时sleep,主线程终止,杀死在处理程序中创建的线程。

这里有很多问题涉及如何将信号定向到单个线程和/或使用sigaction重新启动系统调用(如果这也是您想要解决它的方向)。

于 2013-10-17T03:46:01.080 回答
0

pthread_join你的pthread_create.

于 2013-10-17T03:27:23.533 回答