int pid = fork();
if(pid > 0){
printf("parent: child=%d\n", pid);
pid = wait();
printf("child %d is done\n", pid);
} else if(pid == 0){
printf("child: exiting\n");
exit();
} else {
printf("fork error\n");
}
fork 创建一个新的进程返回两个值 并且共享相同的代码 相当于两个线程同时执行
在父进程中 pid值为子进程的pid
在子进程中 则pid的值为0
输出结果:
parent: child=1234
child: exiting
这种结果是 父进程执行到pid = wait();时候等待子进程退出 但是子进程没有退出
子进程中pid =0 就会执行else if(pid==0)的语句
parent: child 1234 is done这种结果是父进程执行到pid = wait()
子进程已经退出 不在运行了 所以只有父进程一个进程在运行 按顺序执行。
exit函数调用退出进程 并且释放进程占用的资源
System call Description
fork() Create process
exit() Terminate current process
wait() Wait for a child process to exit
kill(pid) Terminate process pid
getpid() Return current process’s id
sleep(n) Sleep for n seconds
exec(filename, *argv) Load a file and execute it
sbrk(n) Grow process’s memory by n bytes
open(filename, flags) Open a file; flags indicate read/write
read(fd, buf, n) Read n byes from an open file into buf
write(fd, buf, n) Write n bytes to an open file
close(fd) Release open file fd
dup(fd) Duplicate fd
pipe(p) Create a pipe and return fd’s in p
chdir(dirname) Change the current directory
mkdir(dirname) Create a new directory
mknod(name, major, minor) Create a device file
fstat(fd) Return info about an open file
link(f1, f2) Create another name (f2) for the file f1
unlink(filename) Remove a file
char *argv[3];
argv[0] = "echo";
argv[1] = "hello";
argv[2] = 0;
exec("/bin/echo", argv);
printf("exec error\n");
这个代码 执行/bin/echo 这个程序并且带有一个参数列表。 echo hello这个参数第一个参数echo可以忽视 大部分程序第一个参数
和程序名一样可以忽略
shell实现echo hello 带参数的流程如下
8500 int main(void)
8502 {
8503 static char buf[100];
8504 int fd;
8505//在主循环中 用geccmd 读取命令行输入的内容
8506 // Assumes three file descriptors open.
8507 while((fd = open("console", O_RDWR)) >= 0){
8508 if(fd >= 3){
8509 close(fd);
8510 break;
8511 }
8512 }
8513
8514 // Read and run input commands.
//在主循环中 用geccmd 读取命令行输入的内容
8515 while(getcmd(buf, sizeof(buf)) >= 0){
8516 if(buf[0] == ’c’ && buf[1] == ’d’ && buf[2] == ’ ’){
8517 // Clumsy but will have to do for now.
8518 // Chdir has no effect on the parent if run in the child.
8519 buf[strlen(buf)-1] = 0; // chop \n
8520 if(chdir(buf+3) < 0)
8521 printf(2, "cannot cd %s\n", buf+3);
8522 continue;
8523 }
//创建一个子进程共享shell中 if下面的代码 此时子进程 执行runcmd 父进程处于wait状态
//如果用户输入 echo hello 则runcmd将以"echo hello"作为参数
8524 if(fork1() == 0)
8525 runcmd(parsecmd(buf));
8526 wait();
8527 }
8528 exit();
8529 }
下面为runcmd的代码
8404 // Execute cmd. Never returns.
8405 void
8406 runcmd(struct cmd *cmd)
8407 {
8408 int p[2];
8409 struct backcmd *bcmd;
8410 struct execcmd *ecmd;
8411 struct listcmd *lcmd;
8412 struct pipecmd *pcmd;
8413 struct redircmd *rcmd;
8414
8415 if(cmd == 0)
8416 exit();
8417
8418 switch(cmd->type){
8419 default:
8420 panic("runcmd");
8421//如果执行到这里的 话 就会执行exec(ecmd->argv[0], ecmd->argv);函数 则就会用echo程序 代替主程序中的runcmd程序 在echo
//中调用exit 函数造成子进程结束 父进程 wait()状态也将会结束掉 因为wait函数一直会等到子进程挂掉 并且返回子进程的pid
8422 case EXEC:
8423 ecmd = (struct execcmd*)cmd;
8424 if(ecmd->argv[0] == 0)
8425 exit();
8426 exec(ecmd->argv[0], ecmd->argv);
8427 printf(2, "exec %s failed\n", ecmd?>argv[0]);
8428 break;
8429
8430 case REDIR:
8431 rcmd = (struct redircmd*)cmd;
8432 close(rcmd->fd);
8433 if(open(rcmd->file, rcmd->mode) < 0){
8434 printf(2, "open %s failed\n", rcmd?>file);
8435 exit();
8436 }
8437 runcmd(rcmd->cmd);
8438 break;
8439
8440 case LIST:
8441 lcmd = (struct listcmd*)cmd;
8442 if(fork1() == 0)
8443 runcmd(lcmd?>left);
8444 wait();
8445 runcmd(lcmd?>right);
8446 break;
8450 case PIPE:
8451 pcmd = (struct pipecmd*)cmd;
8452 if(pipe(p) < 0)
8453 panic("pipe");
8454 if(fork1() == 0){
8455 close(1);
8456 dup(p[1]);
8457 close(p[0]);
8458 close(p[1]);
8459 runcmd(pcmd?>left);
8460 }
8461 if(fork1() == 0){
8462 close(0);
8463 dup(p[0]);
8464 close(p[0]);
8465 close(p[1]);
8466 runcmd(pcmd?>right);
8467 }
8468 close(p[0]);
8469 close(p[1]);
8470 wait();
8471 wait();
8472 break;
8473
8474 case BACK:
8475 bcmd = (struct backcmd*)cmd;
8476 if(fork1() == 0)
8477 runcmd(bcmd?>cmd);
8478 break;
8479 }
8480 exit();
8481 }
版权声明:本文为博主原创文章,未经博主允许不得转载。