父子进程:
1.子进程继承了父进程的内容
2.父子进程有独立的地址空间,互不影响
3.若父进程先结束:
子进程成为孤儿进程,被int进程收养
子进程变为后台进程
4.若子进程先结束
父进程如果没有回收子进程,子进程变为僵尸进程
进程创建:
#include
pid_t fork(void);
创建新的进程,失败返回-1
成功时父进程返回子进程号,子进程返回0
通过fork的返回值区分父进程和子进程
示例:
pid_t pid;
if((pid = fork()) < 0)
{
perror("fork");
return -1;
}
else if(pid == 0)
{
printf("child process pid is %d\n",getpid());
}
else
{
printf("father process pid is %d\n",getpid());
}
进程结束:
#include
#include
void exit(int status);
void _exit(int status);
结束当前进程,并将status返回
exit结束进程时会刷新流缓冲区
exit(0) 表示程序正常退出,exit⑴/exit(-1)表示程序异常退出。
示例:
#include
#include
int main(void)
{
printf("this process will exit");
exit(0);
printf("never be displayed");
}
结果:
./a.out
this process will be exit
示例2:
#include
#include
int main(void)
{
printf("using exit...\n");
printf("this is the end");
exit(0);
}
结果:
./a.out
using exit...
this is the end
exec函数族:
1.进程调用exec函数族执行某个程序
2.进程当前内容被指定程序替换,进程号不变
3.实现让父子进程执行不同程序:
父进程创建子进程
子进程调用exec函数族
父进程不受影响
execl/execlp函数:
#include
int execl(const char *path,const char *arg,...);
int execlp(const char *file,const char *arg,...);
成功时执行指定的程序,失败返回EOF
path 执行的程序名称 包含路径
arg...传递给执行程序的参数列表
file 执行的程序名称,在PATH中查找
这两个函数最后一个参数必须是NULL
示例:
执行ls命令,显示/etc目录下所有文件的详细信息
if(execl("/bin/ls","ls","-a","-l","/etc",NULL) < 0)
{
perror("execl");
}
if(execlp("ls","ls","-a","-l","/etc",NULL) < 0)
{
perror("execlp");
}
execv / execvp函数:
#include
int execv(consr char *path,char *const argv[]);
int execvp(const char *file,char *const argv[]);
成功时执行指定程序,失败返回EOF
arg...封装成指针数组的形式
示例:
执行ls命令,显示/etc目录下所有文件的信息
char *arg[] = {"ls","-a","-l","/etc",NULL};
if(execv("/bin/ls",arg) < 0)
{
perror("execv");
}
if(execvp("ls",arg) < 0)
{
perror("execvp");
}
system函数:
#include
int system(const char *command);
成功时返回命令command的返回值,失败返回EOF
当前进程等待command执行结束后才继续执行
进程回收:
wait()函数:
#include
pid_t wait(int *status);
成功时返回回收的子进程进程号,失败返回EOF
若子进程没有结束,父进程已知阻塞
若有多个子进程,哪个先结束就先回收
status指定保存子进程返回值和结束方式的地址
status为NULL表示直接释放子进程PCB,不接收返回值
wait()函数不能回收指定进程
示例:
int status;
pid_t pid;
if((pid = fork()) < 0)
{
perro("fork");
exit(-1);
}
else if(pid == 0)
{
sleep(1);
exit(2);
}
else
{
wait(&status);
printf("%x\n",status);
}
进程返回值和结束方式:
1.子进程通过exit/_exit/return返回某个值(0-255)
2.父进程调用wait(&status)回收
WIFEXITED(status) 判断子进程是否正常结束
WEXITSTATUS(status) 获取子进程返回值
WIFSIGNALED(status) 判断子进程是否被信号结束
WTERMSIG(status) 获取结束子进程的信号类型
进程回收:
#include
pid_t waitpid(pid_t pid,int *status,int option);
成功时返回回收的子进程的pid或0(表示进程未结束),失败返回EOF
pid可用于指定回收哪个子进程或者任意子进程
status指定用于保存子进程返回值或结束方式的地址
option指定回收方式,0或WNOHANG
0:阻塞方式 若回收子进程未结束,父进程会阻塞,直到子进程结束 相当于 wait() 函数
WNOHANG:非阻塞方式 若子进程未结束,父进程不会阻塞,会立刻从waitpid()返回0,返回值大于0 子进程结束 回收成功
waitpid(pid,&status,0);
waitpid(pid,&status,WNOHANG);
waitpid(-1,&status,0); 等价于 wait()
waitpid(-1,&status,WNOHANG);
-1表示当前进程的任意一个进程