1)获取ID
#include<sys/types.h>
#include<unistd.h>
//获取本进程ID
pid_t getpid(void)
//获取父进程ID
pid_t getppid(void)
2)进程创建-fork
#include<unistd.h>
pid_t fork(void)
功能:创建子进程。fork神奇地被调用一次,却返回两次(父进程当中返回一次,子进程当中返回一次),fork()之后的代码在两个进程中同时运行。它可能有三种不同返回值:
<1> 在父进程中,fork返回新创建的子进程PID;
<2> 在子进程中,fork返回0;
<3> 如果出现错误,fork返回一个负值。
例:fork.c
#include<sys/types.h>
#include<unistd.h>
void main(void) {
pid_t pid;
/* 此时仅有一个进程 */
pid = fork();
/* 此时已经有两个进程同时运行,以下代码getpid()会获取不同的pid */
if (pid < 0)
//父进程中运行
printf("error in fork");
else if (pid == 0)
//子进程中运行
printf("I am the chlid process, ID is %d\n", getpid());
else
//父进程中运行
printf("I am the parent process, ID is %d\n", getpid());
}
总结:在pid=fork()之前,只有一个进程在执行,但在这条语句执行之后,就变成两个进程在执行了,这两个进程的共享代码段,将要执行的下一条语句都是if(pid==0)。两个进程中,原来存在的那个进程被称为“父进程”,新出现的那个进程被称作“子进程”,父子进程的区别在于进程标识符(PID)不同。
注意:fork()之后,父子进程的代码段共享,但数据段不共享,在fork的时候子进程会copy父进程的数据段,创建自己的独立数据段,如下程序:
#include<unistd.h>
#include<stdio.h>
int main(void) {
pid t_pid;
int count = 0;
pid = fork();
count ++;
printf("count = %d\n", count);
return 0;
}
最终会打印两条count = 1。因为在fork以后子进程copy了父进程的代码段,拥有了自己的count变量,count++运算父子进程的count数据互不影响。
3)进程创建-vfork
#include<sys/types.h>
#include<unistd.h>
pid_t vfork(void)
功能:创建子进程
fork与vfork的区别:
fork:子进程拷贝父进程数据段
vfork:子进程与父进程共享数据段
fork:父子进程的执行次序不确定
vfork:子进程先运行,父进程后运行
4)exec函数族
exec用被执行的程序替换调用它的程序。仅仅替换程序代码,不替换进程。
区别:
fork创建一个新的进程,产生一个新的PID。
exec启动一个新程序,替换原有的进程,因此进程的PID不变。
#include<unistd.h>
int execl(const char *path, const char *arg1, ...)
参数:
path: 被执行程序名(含完整路径)。
arg1~argn:被执行程序所需的命令行参数,含程序名,以空指针(NULL)结束。
例:
#include<unistd.h>
void main() {
execl("/bin/ls","ls","-l","/dev", (char *)0);
}
注意:不能直接execl("/bin/ls", "ls -l /dev ", (char *)0);
#include<unistd.h>
int execlp(const char *path, const char *arg1, ...)
参数:
path:被执行程序名(不包含路径,将从path环境变量中查找该程序)。
arg1~argn:被执行程序所需的命令行参数,含程序名,以NULL结束。
例:
#include<unistd.h>
void main() {
execlp("ls","ls","-l","/dev", (char *)0);
}
#include<unistd.h>
int execv(const char *path, char *const argv[ ])
参数:
path:被执行程序名(含完整路径)
argv[ ]:被执行程序所需命令行参数数组。
例:
#include<unistd.h>
void main() {
char *argv[] = {"ls", "-l", "/dev", (char *)0};
execv("/bin/ls",argv);
}
#include<stdlib.h>
int system(const char *string)
功能:调用fork产生子进程,由子进程来调用 /bin/sh -c string 来执行参数string所代表的命令。
例:
#include<stdlib.h>
void main() {
system("ls -l /dev");
}
5)进程等待
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *status)
功能:阻塞该进程,直到他的某个子进程退出,该进程会由阻塞态变为就绪态而非运行态,是否会马上进入运行态要看其优先级是否最高而定。
例:
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
void main() {
pid_t pc, pr;
pc = fork();
if (pc==0) { //如果是子进程
printf("This is child process with pid of %d\n", getpid());
sleep(10); //睡眠10秒钟
} else id (pc>0) { //如果是父进程
pr = wait(NULL); //等待
printf("I catched a child process with pid of %d\n", pr);
}
exit(0); //进程退出
}