在 C 中向子进程发送信号时遇到问题
我一直在试图弄清楚这是否可能像我所做的那样。该程序应该分叉一个循环打印到 STDOUT 的子进程,并且父进程应该退出以返回终端提示符。然后,孩子应该等待 SIGINT 告诉它何时关闭。不过,我记得读过 SIGINT 仅发送到前台进程,这解释了为什么我被遗弃的孩子不受 CTRL+C 的影响。有没有办法让被遗弃的孩子接收从终端发送的信号,或者终端中的某些系统调用将其带到可以接收 SIGINT 的前台?或者我的寻找毫无希望?
代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
/* signal handler for the child process */
void catchInt (int signum)
{
printf("\nMy sincerest apologies, master\n");
exit(0);
}
/* signal handler for the parent process */
void ignoreInt (int signum)
{
/* prevent any extra output from being printed */
fflush(stdout);
/* wait for child to apologize before replying */
wait(NULL);
printf("You're welcome\n");
exit(0);
}
/* signal handler for the child's alarm */
void catchAlarm (int signum)
{
printf("It's great to be alive\n");
/* reset the alarm */
signal(SIGALRM, catchAlarm);
alarm(3);
}
int main () {
pid_t pid;
/* fork process */
pid = fork();
if (pid < 0) /* error handler */
{
fprintf(stderr, "Fork Failed");
exit(-1);
}
/* child */
else if (pid == 0)
{
printf("It's great to be alive\n");
/* catch SIGINT and handle as the child should */
signal(SIGINT, catchInt);
/* catch SIGALRM being sent by alarm() */
signal(SIGALRM, catchAlarm);
/* set alarm for 3 seconds */
alarm(3);
for ( ;; )
{
printf("I have 42001 children and not one comes to visit\n");
usleep(500000);
}
}
/* parent */
else
{
/* exit to abandon child process in the background */
exit(0);
}
return(0);
}
I've been trying to figure out if this is possible the way I've done it or not. This program should fork a child process that loops printing to STDOUT, and the parent should exit to return the terminal prompt. The child should then be waiting for SIGINT to tell it when to close down. However I remember reading that SIGINT is only send to processes in the foreground, which explains why my abandoned child isn't affected by CTRL+C. Is there any way to either get the abandoned child to receive a signal sent from the terminal, or some system call in the terminal to bring it to the foreground where it can receive SIGINT? Or is my search hopeless?
Code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
/* signal handler for the child process */
void catchInt (int signum)
{
printf("\nMy sincerest apologies, master\n");
exit(0);
}
/* signal handler for the parent process */
void ignoreInt (int signum)
{
/* prevent any extra output from being printed */
fflush(stdout);
/* wait for child to apologize before replying */
wait(NULL);
printf("You're welcome\n");
exit(0);
}
/* signal handler for the child's alarm */
void catchAlarm (int signum)
{
printf("It's great to be alive\n");
/* reset the alarm */
signal(SIGALRM, catchAlarm);
alarm(3);
}
int main () {
pid_t pid;
/* fork process */
pid = fork();
if (pid < 0) /* error handler */
{
fprintf(stderr, "Fork Failed");
exit(-1);
}
/* child */
else if (pid == 0)
{
printf("It's great to be alive\n");
/* catch SIGINT and handle as the child should */
signal(SIGINT, catchInt);
/* catch SIGALRM being sent by alarm() */
signal(SIGALRM, catchAlarm);
/* set alarm for 3 seconds */
alarm(3);
for ( ;; )
{
printf("I have 42001 children and not one comes to visit\n");
usleep(500000);
}
}
/* parent */
else
{
/* exit to abandon child process in the background */
exit(0);
}
return(0);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您希望您的孩子在控制终端上击中中断字符时收到
SIGINT
,则它需要位于前台进程组中。您可以实现这一点:(不过,您必须等到父级退出后 shell 更改前台进程组 - 我不确定是否有比循环旋转更好的方法,如示例所示。欢迎提出建议...)
PS: 请注意,前台进程组可以随时更改 - 例如,当另一个进程从 shell 运行时。我不确定你的最终目标是什么,但也许有更好的方法来做到这一点,无论它是什么。
If you want your child to recieve
SIGINT
when the interrupt character is hit on the controlling terminal, it needs to be in the foreground process group. You can achieve this:(You have to wait until the shell changes the foreground process group after your parent exits, though - I'm not sure of a better way to do that than spinning in a loop, as in the example. Suggestions welcome...)
PS: Be aware that the foreground process group can change at any time - for example, when another process is run from the shell. I'm not sure exactly what your end goal is, but maybe there's a better way to do it, whatever it is.
您可以使用
kill
命令向指定的进程号发送信号:当然,如果您的代码识别要杀死哪个PID(子进程在开始循环时应该报告其PID),这会有所帮助。但是,只需进行一些细微的更改(例如省略未使用的ignoreInt()函数,并报告子进程的PID),它就可以正常工作,并且kill命令也可以对其进行工作。
压缩代码:
如果要包含。)
,它通常应该是 POSIX 标头中的第一个(因此位于
之前)代码>)。它被列在最后的事实表明您根本不需要它 - 但我似乎记得之前的一个问题,您断言这是必要的。 (OTOH,没有调用任何wait()
系列,因此
是不必要的,并且我有一定程度的确信 <大多数现代系统不需要 code>You can use the
kill
command to send a signal to a specified process number:Of course, it helps if your code identifies which PID to kill (the child should report its PID when it starts looping). But with just trivial changes (like omitting the unused ignoreInt() function, and reporting the child process's PID), it worked OK as written - and the kill command worked on it too.
Compressed code:
If you are going to include
<sys/types.h>
, it should normally be the first of the POSIX headers (and hence before<unistd.h>
). The fact that it is listed last suggests that you should not need it at all - but I seem to remember a previous question where you asserted that it was necessary. (OTOH, there is no call to any of thewait()
family, so<sys/wait.h>
is unnecessary, and I'm moderately convinced that<sys/types.h>
is not needed on most modern systems.)不,
SIGINT
信号仅在使用 CTRLC(或任何 code>stty 将intr
击键设置为)。您始终可以使用
kill -INT 99999
向特定进程发送 SIGINT(其中99999
是进程 ID)。No, the
SIGINT
signal is only sent to foreground processes when it's actioned by using CTRLC (or whateverstty
has theintr
keystroke set to).You can always send a SIGINT to a specific process with
kill -INT 99999
(where99999
is the process ID).