1. 创建进程(fork)
在Linux中,为了创建一个进程,父进程用系统调用
fork()
来创建子进程。
fork()
会产生一个新的子进程,其子进程会复制父进程的数据与堆栈空间;并继承父进程的用户代码、组代码、环境变量、已打开的文件代码、工作目录和资源限制等。
由于这些继承的信息是复制而来的,并非指相同的内存空间,因此子进程对这些变量的修改和父进程并不会同步。
此外,子进程不会继承父进程的文件锁定和未处理的信号。
#include <sys/types.h>
#include <unistd.h>pid_t fork(void);
进程创建成功后,让它执行与父进程不同的功能。
fork
对子进程返回0,对父进程返回子进程的ID,错误则小于0的错误码
Linux使用
copy-on-write(COW)
技术,只有当其中一进程试图修改欲复制的空间时才会做真正的复制动作。
Linux不保证子进程会比父进程先执行或晚执行,因此编写程序时要留意死锁或竞争条件的发生。
2. 获取进程PID
2.1 getpid()
用来获取当前进程的进程
pid
,许多程序利用取到的此值来创建临时文件,避免临时文件相同带来的问题返回值:当前进程的
pid
。
#include <unistd.h>pid_t getpid(void)
2.2 getppid()
用于获取目前进程的父进程
pid
返回值 目前进程的父进程
pid
#include <unistd.h>pid_t getpid(void)
3. 进程阻塞(wait)
即 休眠/阻塞 来等待信号或父进程等待子进程退出(再回收其资源)
#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);
wait
- 等待任意一个子进程退出或状态发生改变waitpid
- 等待一个(一些)子进程的状态发生改变
参数
wstatus
: 指向的空间,用来保存子进程的退出信息。pid
: 指定等待的进程或进程组-1
: 表示等待任意的子进程退出0
: 表示等待与调用进程同组的任意子进程。<-1
: 表示等待组ID等于pid
绝对值的那个组的任意子进程>0
: 表示等待指定的子进程
options
: 等待选项0
: 表示阻塞等待WNOHANG
: 非阻塞等待,如果没有子进程退出,则立即返回。
返回值
- 成功 : 返回退出的那个子进程的
pid
- 失败 : 返回-1,同时
errno
被设置
4. 进程分离 (exec函数族)
读取另一个程序文件,并在当前的进程空间执行。
exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段、数据段和堆栈等都已经被新的内容取代。只有调用失败了,它们才会返回
-1
,从原程序的调用点接着往下执行。
#include <unistd.h>extern char **environ;int execl(const char *pathname, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *pathname, const char *arg, ...);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
参数
pathname
: 程序文件路径file
: 指定文件名 (从环境变量中寻找)arg
: 参数
5. 进程退出(exit)
_exit()
用来立刻结束目前进程的执行,并把参数status
返回给父进程,并关闭未关闭的文件。此函数调用后不会返回,并且会传递SIGCHLE
信号给父进程,父进程可以有wait
函数取得子进程结束状态。
_exit()
不会处理标准I/O
缓冲区,如要更新缓冲区请使用exit()
。
#include <stdlib.h>void exit(int status);
void _exit(int status);