也可以称为系统调用。
fork
在unix中,创建新的进程可以使用fork。
#include "syscalls.h"
int main(int argc,char *argv[])
{
printf("hello,world (pid:%ld)\n",(long)getpid());
long rc = fork();
if(rc < 0)
{
fprintf(stderr,"forl failed\n");
exit(1);
} else if(rc == 0){
printf("hello,I am child(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
} else{
printf("hello,I am parent(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
}
return 0;
}
输出就像这样:
hello,world (pid:28244)
hello,I am parent(pid:28244)->(forkReturn:28245)
hello,I am child(pid:28245)->(forkReturn:0)
关于fork创建的子进程,有几点需要知道。首先,子进程几乎是父进程的一个精确的拷贝,就是二者几乎完全一样。所以,子进程不需要从main开始运行。
子进程有自己的私有PC,私有地址空间,自己的寄存器等等。当父进程收到子进程的PID时,子进程得到一个0的返回值。这个返回值是指fork的返回值。
也就是说,fork返回给父进程子进程的PID,子进程得到的是0.具体可查看代码输出。
以上代码的输出顺序是不固定的。书上说是不固定的,但是我试了好多次都是固定的,可能,虽然我也认同不是固定的。
wait
等待子进程完成。
#include "syscalls.h"
int main(int argc,char *argv[])
{
printf("hello,world (pid:%ld)\n",(long)getpid());
long rc = fork();
if(rc < 0)
{
fprintf(stderr,"forl failed\n");
exit(1);
} else if(rc == 0){
printf("hello,I am child(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
} else{
int wc = wait(NULL);
printf("hello,I am parent(pid:%ld)->(forkReturn:%ld)->(waitReturn:%d)\n",(long)getpid(),rc,wc);
}
return 0;
}
输入如下:
hello,world (pid:28906)
hello,I am child(pid:28907)->(forkReturn:0)
hello,I am parent(pid:28906)->(forkReturn:28907)->(waitReturn:28907)
wait的返回值是子进程pid。
输出顺序固定。
exec
这个系统调用是用来运行其他程序的,创建基于其他程序的进程。
#include "syscalls.h"
int main(int argc,char *argv[])
{
printf("hello,world (pid:%ld)\n",(long)getpid());
long rc = fork();
if(rc < 0)
{
fprintf(stderr,"forl failed\n");
exit(1);
} else if(rc == 0){
char *myargs[3];
myargs[0] = strdup("wc");
myargs[1] = strdup("ostep_exec.c");
myargs[2] = NULL;
execvp(myargs[0],myargs);
printf("this should not print out");
printf("hello,I am child(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
} else{
int wc = wait(NULL);
printf("hello,I am parent(pid:%ld)->(forkReturn:%ld)->(waitReturn:%d)\n",(long)getpid(),rc,wc);
}
return 0;
}
输出如下:
hello,world (pid:29268)
30 66 767 ostep_exec.c
hello,I am parent(pid:29268)->(forkReturn:29269)->(waitReturn:29269)
exec的调用重新初始化了地址空间,包括堆栈等。以及代码和静态数据。
但是exec的pid和fork得到的pid是一样的。
tips:调用fork部分的实例代码
#include "syscalls.h"
int main(int argc,char *argv[])
{
printf("hello,world (pid:%ld)\n",(long)getpid());
long rc = fork();
if(rc < 0)
{
fprintf(stderr,"forl failed\n");
exit(1);
} else if(rc == 0){
char *myargs[3];
myargs[0] = strdup("./process");
myargs[1] = NULL;
myargs[2] = NULL;
execvp(myargs[0],myargs);
printf("this should not print out");
printf("hello,I am child(pid:%ld)->(forkReturn:%ld)\n",(long)getpid(),rc);
} else{
int wc = wait(NULL);
printf("hello,I am parent(pid:%ld)->(forkReturn:%ld)->(waitReturn:%d)\n",(long)getpid(),rc,wc);
}
return 0;
}
网友评论