1.fork
pid_ t fork(void);
返回值:子进程返回0,父进程返回子进程的id,出错返回-1
当一个进程调用fork之后,就有两个二进制相同的进程。而且它们都运行到相同的地方。但每个进程都将开始它们自己的旅程。
- 创建一个进程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main( void )
{
printf("before fork\n");
pid_t pid = fork();
if ( pid == 0 ) {
//子进程
while ( 1 )
printf("child\n");
} else if ( pid > 0 ) {
//父进程
while ( 1 )
printf("parent\n");
}else
{
//出错
perror("fork");
exit(1);
}
}
- 写时拷贝
通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int g_data = 250;
int main( void )
{
pid_t pid = fork();
if ( pid == 0 ) {
g_data = 520;
printf("child g_data = %p\n", &g_data);
printf("child value = %d\n", g_data);
} else {
sleep(1);
printf("parent g_data = %p\n", &g_data);
printf("parent value = %d\n", g_data);
}
}
fork调用失败的原因
1.系统中有太多的进程
2.实际用户的进程数超过了限制>2 .vfork函数
- vork用于创建一个子进程,而子进程和父进程共享地址空间,fork的子进程具有独立地址空间
- vork保证子进程先运行,在它调用exec或(exit)之后父进程才可能被调读运行
进程终止
进程退出场景:
- 代码运行完毕,结果正确
- 代码运行完毕,结果不正确
- 代码异常终止
进程常见退出方法:
正常终止:1.从main返回
2.调用exit
3._exit
异常退出:
ctrl + c ,信号终止
_exit函数:
void _exit(int status);
参数:status定义了进程的终止状态,父进程通过wait来获取该值
说明:虽然status是int,但是仅有8为可以被父进程所用。所以_exit(-1)时,在中端执行行$?发现返回值是255。exit函数:
void exit(int status);
exit最后也会调用_exit,但在调用exit之前,还做了其他工作:
1.执行用户通过atexit或on_exit定义的清理函数
2.关闭所有打开的流,所有的缓存数据均被写入
3.调用exit
进程等待
- wait:
#incldue<stdio.h>
#include<stdlib.h>
pid_t wait(int *status);
返回值:成功返回被等待进程pid,失败返回-1
参数:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main(void)
{
pid_t pid = fork();
if( pid == 1)
perror("fork"),exit(EXIT_FAILURE);
if (pid == 0)
{
sleep(20);
printf("哈哈,我死了 pid = %d\n",getpid());
exit(125);
}
else
{
int s;
pid_t r = wait(&s);
printf("r = %d\n",r);
if (WIFEXITED(s))
{
printf("code = %d\n",WEXITSTATUS(s));
}
}
}
- waitpid
pid_t waitpid(pid_t pid,int *status,int option);
返回值:
当正常返回的时候waitpid返回收集到的子进程的进程ID
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在。
参数:
pid:
pid = -1,等待任一个子进程,与wait等效
pid > 0,等待其进程ID与pid相等的子进程
status:
WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看进程是否正常退出)
WEXITSTATUS(status):若WIFDXITED非零,提取子进程退出码。(查看进程的退出码)
options:
WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。