进程号
每个进程初始化时,系统都分配一个ID号,用来标识进程,具有唯一性。
getpid()函数
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(); // 获取当前进程ID
pid_t getppid(); // 获取父进程ID
通过命令 ps -x |grep 进程号, 可查询该进程。
进程复制fork()
#include <sys/types.h>
#include <unistd.h>
pid_t fork(); // 成功返回进程号,失败返回-1;
特点:执行一次,返回两次,在父进程中返回子进程的进程ID号,子进程返回0;
system()方式
system()函数调用 "/bin/sh-c command"执行特定的命令,阻塞当前进程直到command命令执行完毕。
#include <stdlib.h>
int system(const char* command);
执行System()函数时,会调用fork 、execve、waitpid等函数,其中任意一个调用失败将导致system()函数调用失败,system()函数的返回值:
- 失败 -1
- 当sh不能执行时,返回127,
- 成功返回进程状态值。
exec()族函数
fork()和system()函数执行时,系统都会建立一个新的进程,执行调用者的操作,原来的进程还会存在,知道显示退出,而exec()族的函数会用新进程代替原有的进程,系统会从新进程运行,新进程PID值同原来进程一致。
exec()族函数:
#include <unistd.h>
extern char **environ;
int execl(const char* path,const char *arg,...);
int execlp(const char* file,const char *arg,...);
int execle(const char* path,const char *arg,...,char* const envp[]); // 真正系统调用,其他几个则是封装的库函数
int execv(const char* path,const char *arg[]);
int execvp(const char* file,const char *arg[]);
使用exec()普遍的一种用法是先使用fork()函数分叉进程,然后再新的进程中调用exec()函数,这样exec() 占用与原来一样的系统资源来运行。
在fork系统调用之后进行exec()系统调用,系统就不回进行系统复制,此方法叫做写时复制,即只有在造成系统的内容发生更改的时候才进行进程的真正更新。
初始进程init.
pstree 查看系统中运行的进程间的关系。