java 处理 ctrl c_Ctrl-C如何终止子进程?

setpgid POSIX C process group minimal example

使用底层API的最小可运行示例可能更容易理解 .

这说明了如果孩子没有用 setpgid 更改其进程组,信号如何发送给子进程 .

main.c中

#define _XOPEN_SOURCE 700

#include

#include

#include

#include

#include

#include

#include

volatile sig_atomic_t is_child = 0;

void signal_handler(int sig) {

char parent_str[] = "sigint parent\n";

char child_str[] = "sigint child\n";

signal(sig, signal_handler);

if (sig == SIGINT) {

if (is_child) {

write(STDOUT_FILENO, child_str, sizeof(child_str) - 1);

} else {

write(STDOUT_FILENO, parent_str, sizeof(parent_str) - 1);

}

}

}

int main(int argc, char **argv) {

pid_t pid, pgid;

(void)argv;

signal(SIGINT, signal_handler);

signal(SIGUSR1, signal_handler);

pid = fork();

assert(pid != -1);

if (pid == 0) {

/* Change the pgid.

* The new one is guaranteed to be different than the previous, which was equal to the parent's,

* because `man setpgid` says:

* > the child has its own unique process ID, and this PID does not match

* > the ID of any existing process group (setpgid(2)) or session.

*/

is_child = 1;

if (argc > 1) {

setpgid(0, 0);

}

printf("child pid, pgid = %ju, %ju\n", (uintmax_t)getpid(), (uintmax_t)getpgid(0));

assert(kill(getppid(), SIGUSR1) == 0);

while (1);

exit(EXIT_SUCCESS);

}

/* Wait until the child sends a SIGUSR1. */

pause();

pgid = getpgid(0);

printf("parent pid, pgid = %ju, %ju\n", (uintmax_t)getpid(), (uintmax_t)pgid);

/* man kill explains that negative first argument means to send a signal to a process group. */

kill(-pgid, SIGINT);

while (1);

}

编译:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -Wpedantic -o setpgid setpgid.c

Run without setpgid

没有任何CLI参数, setpgid 未完成:

./setpgid

可能的结果:

child pid, pgid = 28250, 28249

parent pid, pgid = 28249, 28249

sigint parent

sigint child

并且该程序挂起 .

正如我们所看到的,两个进程的pgid是相同的,因为它跨 fork 继承 .

然后每当你点击:

Ctrl + C

它又输出:

sigint parent

sigint child

这显示了如何:

使用 kill(-pgid, SIGINT) 向整个进程组发送信号

默认情况下,终端上的Ctrl C会向整个进程组发送一个kill

通过向两个进程发送不同的信号来退出程序,例如SIGQUIT与 Ctrl + \ .

Run with setpgid

如果你使用参数运行,例如:

./setpgid 1

然后孩子改变它的pgid,现在每次只从父母那里打印一个sigint:

child pid, pgid = 16470, 16470

parent pid, pgid = 16469, 16469

sigint parent

现在,每当你点击:

Ctrl + C

只有父母也接收到信号:

sigint parent

您仍然可以像以前一样使用SIGQUIT杀死父级:

Ctrl + \

但是孩子现在有不同的PGID,并且没有收到该信号!这可以从:

ps aux | grep setpgid

你将不得不明确杀死它:

kill -9 16470

这清楚地说明了为什么存在信号组:否则我们会得到一堆剩余的进程以便一直手动清理 .

在Ubuntu 18.04上测试过 .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值