赞
踩
在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。
pid_t fork(void);
//fork函数的头文件
#include <unistd.h>
返回值:创建成功给子进程返回0,父进程返回子进程id,出错返回-1
使用 fork() 函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间:包括进程上下文(进程执行活动全过程的静态描述)、进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号,计时器等(只有小量信息)
。进程调用fork,当控制转移到内核中的fork代码后,内核(OS)做:
#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main(int argc, char *argv[]) { pid_t pid; pid = fork(); if( pid < 0 ){ // 没有创建成功 perror("fork"); } if(0 == pid){ // 子进程 while(1){ printf("I am son\n"); sleep(1); } } else if(pid > 0){ // 父进程 while(1){ printf("I am father\n"); sleep(1); } } return 0; }
运行结果:
之前说,子进程退出,父进程如果不管不顾,就可能造成“僵尸进程”的问题,进而造成内存泄露,进而,进程一旦变成僵尸状态,杀人不眨眼的”kill-9”也无能为力,因为谁也没有办法杀死一个已经死去的进程,最后,父进程派给子进程的任务完成的如何,我们需要知道,如子进程运行完成,结果是还是不对,或者是否正常退出,我们需要知道。
父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息
pid_t wait(int *status)
//头文件
#include<sys/wait.h>
#include<sys/type.h>
返回值:
输出型参数,获取子进程退出状态,不关心则可以设置为NULL
wait进程等待代码示例:
pid_t waitpid(pid_t pid,int *status,int options)
//头文件:
#include<sys/type.h>
#include<sys/wait.h>
返回值:
参数说明:
1.pid
pid=-1,等待任一个子进程,与wait等效
pid>0,等待其进程ID与pid相等的子进程
2.status
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真(此参数是查看进程是否是正常退出)
WEXITSTATUS(status): 若WEXITSTATUS非零,提取子进程退
出码(查看进程的退出码)
3.options
WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待,若正常结束,则返回该子进程的ID
如果子进程已经退出,调用wait/waitpid会立即返回,并且释放资源,获得子进程退出信息
如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞
如果不存在该子进程,则立即出错返回
子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止)
waitpid进程等待代码示例:
wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充
如果传递NULL,表示不关心子进程的退出状态信息,否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程
status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位):
正常终止:
status & 0x7f, 如果是0的话,那就表示正常退出
0xff是0111111,status按位与0x7f,表示取出status的低7位
当正常终止的时候,status高8位就是子进程的退出码
status & 0xff,就是取出status的高8位
异常终止:
status & 0x7f, 不为0的话,那就表示异常退出
代码示例:
正常终止(可以通过 echo $?
查看最近一次进程退出码):
异常退出:
main函数退出时, return的数字就是程序的退出码。 问题: 为什么main的return一般会写成0?
因为0在函数设计中,一般代表正确。非0代表错误。
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
using namespace std;
int main()
{
cout << "hello" << endl;
return 0;//退出码为0
}
void exit(int status);
//头文件
#include <unistd.h>
exit:终止整个进程,任何地方都会调用,都会终止
。return:终止函数。main函数return 代表进程退出
。void _exit(int status);
//头文件
#include <unistd.h>
代码示例:
#include <iostream> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> using namespace std; int exe() { _exit(12); return 12; } int main() { cout << "you should running here!"; sleep(5);//sleep5秒 exit(13); return 0;//退出码为0 }
因此,要想保证数据的完整性,就一定要使用exit()函数
。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。