CSAPP:撸一个Shell(一)

(一)后台进程的读取问题

问题的起因是一段程序1的试验,创建一个父进程,在父进程中创建子进程运行cat,下面是源码。

//程序1
#include"csapp.h"
#include<stdio.h>
#include<signal.h>
int pid=0;
int main(int argc,char **argv)
{
	if((pid=fork())==0)
	{
		printf("child:\n");
		setpgid(0,0);
		execve("/bin/cat",argv,environ);
		exit(0);
	}
	
	 if((pid=waitpid(pid,NULL,WUNTRACED))<0)
	 {
		 printf("error");
	 }

	printf("end\n");
	return 0;
}

但是实际运行的效果是如下图,并没有跑出cat

错误运行:没有执行cat

于是我试着自己写一个程序child模仿cat

//程序b
include"csapp.h"
int main()
{
 char s[20];
 char q[20]="quit";
  printf("start\n");
  while(read(0,s,1)!=0)
      write(1,s,1);
 return 0;
}

运行效果和使用cat作为子进程的时候是一样的,于是我在程序child中加了一个死循环然后用ps查看进程运行的状态

//程序b
include"csapp.h"
int main()
{
 char s[20];
 char q[20]="quit";
  printf("start\n");
while(1)
{
  while(read(0,s,1)!=0)
      write(1,s,1);
}
 return 0;
}
运行效果

可以看到child是处于T(暂停状态)的。后来我试着删掉了创建子进程后的setpgid(0,0),就可以正常运行了:

正常运行:执行cat

setpgid(0,0)是将目前进程的进程组号修改为目前进程的进程号,因此问题即出在了进程组号上,后来我在LINUX KERNEL找到了Foreground Process Group和Background Process Group的定义,才发现了原因的所在。

Among the process groups in a session at most one can be the foreground process group of that session. The tty input and tty signals (signals generated by ^C, ^Z, etc.) go to processes in this foreground process group.

Linux Kernel

一个session里面最多只能有一个进程组, The tty input and tty signals (signals generated by ^C, ^Z, etc.) 会进入到该前台进程组的进程。

原来是因为我们在运行父进程的时候父进程是前台进程组,子进程原本也是和父进程一个组,因此child可以正常接受input正常运行,但是当我们使用setpgid(0,0)即修改了子进程的进程组,这时候他不再属于前台进程组,因此无法接收到tty input,也就是无法接受键盘的输入,子进程无法正常运行。

那么当我写一个SHELL的时候,我需要创建的子进程和父进程不在一个进程组,而且我希望子进程作为前台进程的时候应该如何做呢

A process can set the foreground process group in its session using tcsetpgrp(fd,pgrp), where fd refers to its controlling tty, and pgrp is a process group in the its session, and this session still is associated to the controlling tty of the calling process.

Linux Kernel

使用tcsetpgrp(fd,pgrp),将fd设置为tty input 的文件,将pgrp设置为子进程的进程组,即可以将子进程组设置为前台进程组

//程序1
#include"csapp.h"
#include<stdio.h>
#include<signal.h>
int pid=0;
int main(int argc,char **argv)
{
	if((pid=fork())==0)
	{
		printf("child:\n");
		setpgid(0,0);
		execve("./child",argv,environ);
		exit(0);
	}
	 tcsetpgrp(0,pid);
	 if((pid=waitpid(pid,NULL,0))<0)
	 {
		 printf("error");
	 }

	printf("end\n");
	return 0;
}

运行:

正常运行

正常运行。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇