如果要了解进程和线程的区别请参考:进程和线程的描述
1.fork()函数介绍
#include<sys/types.h>
#include<unistd.h>
pid_t fork(void);
这个函数虽然执行一次,但是会返回2次的不同的值。就是在这里一个进程会变为两个进程,原本的进程叫做父进程,新的进程叫子进程。父进程中返回的值为子进程的ID号。而子进程中返回的是0.
调用这个函数后就产生了2个进程,但是此时的两个进程还没有真正的拥有两个独立的资源,还是共用的一份。只用当其中一个进程发生写的动作,系统才会分配一份新的资源给这个进程。此时才是各自拥有独立的资源。这个叫做写时复用。比如通过函数execve()执行新的程序。
2.execve()函数介绍
#include<unistd.h>
int execve(const char *file, const char *argv[] const char *envp[]);
参数1:要执行的文件
参数2:执行文件后面跟着的参数,可以是NULL;
参数3:环境变量
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
pid_t pid;
pid = fork();
if(pid > 0) {
while(1) {
printf("c : %d, re : %d f : %d\n", pid, getpid(), getppid());
sleep(1);
}
} else if(pid == 0) {
char *args[] = {"/bin/ls", NULL};
execve("/bin/ls", args, NULL);
printf("Process test\n");
printf("c : %d, re : %d f : %d\n", pid, getpid(), getppid());
} else {
printf("process failed\n");
}
return 0;
}
这个函数的意思是,通过fork产生两个进程,父进程执行while(1)打印信息,子进程执行ls命令。你会发现子进程中的打印函数并没有执行,这就是通过execve()执行ls后,子进程就被分配了独立的资源,就进入独立的资源里面去执行,后面的两个打印函数就不是子进程的资源了。如果吧execve去掉就会发现打印会执行,这时就是父子进程共用资源。 只有在execve()执行,就是子进程要发生写时,资源才会分配给它,即为写时复用。
kayshi@ubuntu:~/code/Process$ ./a.out
c : 10086, re : 10085 f : 2157
a.out fork.c
c : 10086, re : 10085 f : 2157
c : 10086, re : 10085 f : 2157
c : 10086, re : 10085 f : 2157
c : 10086, re : 10085 f : 2157
c : 10086, re : 10085 f : 2157
c : 10086, re : 10085 f : 2157
通过pstree可以查看进程树
bash进程下,产生了我们要执行的进程a.out 然后有产生了新的子进程ls