linux shell如何处理后台进程(急啊,给高分)

loe 2015-01-16 09:34:43
刚做了一个小实验:
编辑一个小测试程序

#include <stdio.h>
int main()
{
while(1)
{
sleep(3);
}
return 0;
}

①编辑成可执行文件 ,名为11
②让它在后台运行,在终端执行命令 ./11 &
③打印结果: ps -o pid,ppid,pgrp,comm
PID PPID PGRP COMMAND
3603 3601 3603 bash
3777 3603 3777 11
3780 3603 3780 ps
问题:
从打印结果来看,bash与11不在一个进程组里,这是为什么?
个人对问题的理解:
在终端运行 11 &,理论上shell的处理应该是fork,也就是说11的父进程是bash,这个从结果上看是对的,但如果要独立成为一个进程组的话应该调用setpgid()函数将11变为进程组组长,但我查了下shell的源码,并没有发现有哪个地方调用此函数, 那shell是如何使11这个进程变成进程组组长的呢?
...全文
410 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
loe 2015-01-18
  • 打赏
  • 举报
回复
嗯嗯,非常感谢啊!
zuxi 2015-01-18
  • 打赏
  • 举报
回复
引用 6 楼 mxgsgtc 的回复:
[quote=引用 5 楼 wangzuxi 的回复:] [quote=引用 4 楼 mxgsgtc 的回复:] [quote=引用 3 楼 wangzuxi 的回复:] [quote=引用 2 楼 mxgsgtc 的回复:] [quote=引用 1 楼 wangzuxi 的回复:] 一般都是在C程序里面把自己设置成后台daemon进程。
希望看清问题在回答啊,不过还是很感谢[/quote] shell执行程序是fork+exec方式,shell没调setpgid可以看看fork和exec系统调试里面调没调,看内核代码吧。 setpgid应该只是设置task_struct的某个成员,fork或者exec调用里面也可能直接设置task_struct的这个成员。 只是猜测,还没看代码验证。[/quote] 理论上fork+exec函数的话进程组id是不会改变的,这个通过做实验写一个应用程序里面fork+exec调用另一个应用程序,发现他们的进程组id是一样的,我看的linux 0.12的内核代码,整个内核代码中,setpgid中是作为系统调用的,内核函数exec与fork并没有对pgid这个变量做什么处理,也许我看的不仔细,我在看看,不过可以肯定的是,将进程变成进程组组长肯定是shell的行为,但怎么变的真不清楚啊。。。我的猜测是肯定调用的setpgid函数,真不知道还有什么方式啊[/quote] 用gdb跟了一下bash,设断点: b setpgid,调用堆栈如下: (gdb) bt #0 setpgid () at ../sysdeps/unix/syscall-template.S:82 #1 0x0000000000443373 in make_child () #2 0x00000000004329a1 in execute_command_internal () #3 0x00000000004352fe in execute_command () #4 0x000000000041e31d in reader_loop () #5 0x000000000041ca87 in main () 如果是自己fork出来的子进程,那子进程的pgid是父进程的pid,代码如下:

static struct task_struct *copy_process(unsigned long clone_flags,
					unsigned long stack_start,
					unsigned long stack_size,
					int __user *child_tidptr,
					struct pid *pid,
					int trace)
{
……
    if (likely(p->pid)) {
		ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);

		init_task_pid(p, PIDTYPE_PID, pid);
		if (thread_group_leader(p)) {
			init_task_pid(p, PIDTYPE_PGID, task_pgrp(current));//把当前进程的pid设置子进程的pgid
……
}是吗
[/quote] 非常感谢你的回复!才看到回复实在抱歉,还是有点不太明白你的意思: 一: bash是调用了setpgid了是吗?[/quote] 对,是的。你可以下载bash的最新代码看一下,在这个函数里make_child有调用setpgid。
loe 2015-01-18
  • 打赏
  • 举报
回复
引用 5 楼 wangzuxi 的回复:
[quote=引用 4 楼 mxgsgtc 的回复:] [quote=引用 3 楼 wangzuxi 的回复:] [quote=引用 2 楼 mxgsgtc 的回复:] [quote=引用 1 楼 wangzuxi 的回复:] 一般都是在C程序里面把自己设置成后台daemon进程。
希望看清问题在回答啊,不过还是很感谢[/quote] shell执行程序是fork+exec方式,shell没调setpgid可以看看fork和exec系统调试里面调没调,看内核代码吧。 setpgid应该只是设置task_struct的某个成员,fork或者exec调用里面也可能直接设置task_struct的这个成员。 只是猜测,还没看代码验证。[/quote] 理论上fork+exec函数的话进程组id是不会改变的,这个通过做实验写一个应用程序里面fork+exec调用另一个应用程序,发现他们的进程组id是一样的,我看的linux 0.12的内核代码,整个内核代码中,setpgid中是作为系统调用的,内核函数exec与fork并没有对pgid这个变量做什么处理,也许我看的不仔细,我在看看,不过可以肯定的是,将进程变成进程组组长肯定是shell的行为,但怎么变的真不清楚啊。。。我的猜测是肯定调用的setpgid函数,真不知道还有什么方式啊[/quote] 用gdb跟了一下bash,设断点: b setpgid,调用堆栈如下: (gdb) bt #0 setpgid () at ../sysdeps/unix/syscall-template.S:82 #1 0x0000000000443373 in make_child () #2 0x00000000004329a1 in execute_command_internal () #3 0x00000000004352fe in execute_command () #4 0x000000000041e31d in reader_loop () #5 0x000000000041ca87 in main () 如果是自己fork出来的子进程,那子进程的pgid是父进程的pid,代码如下:

static struct task_struct *copy_process(unsigned long clone_flags,
					unsigned long stack_start,
					unsigned long stack_size,
					int __user *child_tidptr,
					struct pid *pid,
					int trace)
{
……
         if (likely(p->pid)) {
		ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);

		init_task_pid(p, PIDTYPE_PID, pid);
		if (thread_group_leader(p)) {
			init_task_pid(p, PIDTYPE_PGID, task_pgrp(current));//把当前进程的pid设置子进程的pgid
……
}是吗
[/quote] 非常感谢你的回复!才看到回复实在抱歉,还是有点不太明白你的意思: 一: bash是调用了setpgid了是吗?
zuxi 2015-01-17
  • 打赏
  • 举报
回复
引用 4 楼 mxgsgtc 的回复:
[quote=引用 3 楼 wangzuxi 的回复:] [quote=引用 2 楼 mxgsgtc 的回复:] [quote=引用 1 楼 wangzuxi 的回复:] 一般都是在C程序里面把自己设置成后台daemon进程。
希望看清问题在回答啊,不过还是很感谢[/quote] shell执行程序是fork+exec方式,shell没调setpgid可以看看fork和exec系统调试里面调没调,看内核代码吧。 setpgid应该只是设置task_struct的某个成员,fork或者exec调用里面也可能直接设置task_struct的这个成员。 只是猜测,还没看代码验证。[/quote] 理论上fork+exec函数的话进程组id是不会改变的,这个通过做实验写一个应用程序里面fork+exec调用另一个应用程序,发现他们的进程组id是一样的,我看的linux 0.12的内核代码,整个内核代码中,setpgid中是作为系统调用的,内核函数exec与fork并没有对pgid这个变量做什么处理,也许我看的不仔细,我在看看,不过可以肯定的是,将进程变成进程组组长肯定是shell的行为,但怎么变的真不清楚啊。。。我的猜测是肯定调用的setpgid函数,真不知道还有什么方式啊[/quote] 用gdb跟了一下bash,设断点: b setpgid,调用堆栈如下: (gdb) bt #0 setpgid () at ../sysdeps/unix/syscall-template.S:82 #1 0x0000000000443373 in make_child () #2 0x00000000004329a1 in execute_command_internal () #3 0x00000000004352fe in execute_command () #4 0x000000000041e31d in reader_loop () #5 0x000000000041ca87 in main () 如果是自己fork出来的子进程,那子进程的pgid是父进程的pid,代码如下:

static struct task_struct *copy_process(unsigned long clone_flags,
					unsigned long stack_start,
					unsigned long stack_size,
					int __user *child_tidptr,
					struct pid *pid,
					int trace)
{
……
         if (likely(p->pid)) {
		ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);

		init_task_pid(p, PIDTYPE_PID, pid);
		if (thread_group_leader(p)) {
			init_task_pid(p, PIDTYPE_PGID, task_pgrp(current));//把当前进程的pid设置子进程的pgid
……
}
loe 2015-01-16
  • 打赏
  • 举报
回复
引用 3 楼 wangzuxi 的回复:
[quote=引用 2 楼 mxgsgtc 的回复:] [quote=引用 1 楼 wangzuxi 的回复:] 一般都是在C程序里面把自己设置成后台daemon进程。
希望看清问题在回答啊,不过还是很感谢[/quote] shell执行程序是fork+exec方式,shell没调setpgid可以看看fork和exec系统调试里面调没调,看内核代码吧。 setpgid应该只是设置task_struct的某个成员,fork或者exec调用里面也可能直接设置task_struct的这个成员。 只是猜测,还没看代码验证。[/quote] 理论上fork+exec函数的话进程组id是不会改变的,这个通过做实验写一个应用程序里面fork+exec调用另一个应用程序,发现他们的进程组id是一样的,我看的linux 0.12的内核代码,整个内核代码中,setpgid中是作为系统调用的,内核函数exec与fork并没有对pgid这个变量做什么处理,也许我看的不仔细,我在看看,不过可以肯定的是,将进程变成进程组组长肯定是shell的行为,但怎么变的真不清楚啊。。。我的猜测是肯定调用的setpgid函数,真不知道还有什么方式啊
zuxi 2015-01-16
  • 打赏
  • 举报
回复
引用 2 楼 mxgsgtc 的回复:
[quote=引用 1 楼 wangzuxi 的回复:] 一般都是在C程序里面把自己设置成后台daemon进程。
希望看清问题在回答啊,不过还是很感谢[/quote] shell执行程序是fork+exec方式,shell没调setpgid可以看看fork和exec系统调试里面调没调,看内核代码吧。 setpgid应该只是设置task_struct的某个成员,fork或者exec调用里面也可能直接设置task_struct的这个成员。 只是猜测,还没看代码验证。
loe 2015-01-16
  • 打赏
  • 举报
回复
引用 1 楼 wangzuxi 的回复:
一般都是在C程序里面把自己设置成后台daemon进程。
希望看清问题在回答啊,不过还是很感谢
zuxi 2015-01-16
  • 打赏
  • 举报
回复
一般都是在C程序里面把自己设置成后台daemon进程。

23,107

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧