fork、wait、waitpid、execl、execlp、dump2函数相关内容

fork、wait、waitpid、execl、execlp、dump2函数相关内容:

1.fork()函数
pid_t fork( void); 创建子进程
pid_t 是一个宏定义,其实质是int 被定义在#include<sys/types.h>中
返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。
子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间(读时共享,写时复制)
fork的另一个特性是所有由父进程打开的描述符都被复制到子进程中。父、子进程中相同编号的文件描述符在内核中指向同一个file结构体,也就是说,file结构体的引用计数要增加。

2.wait()函数
pid_t wait(int *status)
头文件:#include <sys/types.h> #include <wait.h>
传出参数:子进程状态值的地址(如果不在意结束状态值,则参数 status 可以设成 NULL。)
返回值:子进程成功被回收,返回被回收的子进程PID;无可回收的子进程,返回-1
函数功能:父进程一旦调用了wait就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

3.waitpid()函数
pid_t waitpid(pid_t pid,int * status,int options);
函数功能:如果在调用 waitpid()时子进程已经结束,则 waitpid()会立即
返回子进程结束状态值。 子进程的结束状态值会由参数 status 返回,
而子进程的进程PID也会一起返回。
如果不在意结束状态值,则参数 status 可以设成 NULL。

参数 pid 为欲等待的子进程识别码,其他数值意义如下:
pid<-1 等待进程组识别码为 pid 绝对值的任何子进程。
pid=-1 等待任何子进程,相当于 wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为 pid 的子进程。
参数3 options:
WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若结束,则返回该子进程的ID。(非阻塞)

返回值:
成功回收子进程,返回子进程PID
无可回收的子进程,返回-1
当参数3为WNOHANG时,且子进程未结束,立即返回,不予等待,返回值为0

wait()和waitpid()总结:
wait()和waitpid()都是一次仅回收一个子进程,如需多次回收,则使用for循环或者while循环。

wait(&status) 等同于 waitpid(-1,&status,0); 阻塞等待子进程结束

函数的传出参数status,可以用于收集子进程结束状态情况和返回值等数据:
WIFEXITED(status);–如果子进程正常退出,则为真
在正常退出的情况下,也就是WIFEXITED(status)为真的情况下,使用WEXITSTATUS(status)获取子进程返回值。一般会先用 WIFEXITED 来判断是否正常结束才能使用此宏。

WIFSIGNALED(status)—当子进程由于收到某种信号退出时,则为真
(进程的异常结束都是收到了信号,当程序出错结束时,也是收到了信号)
在程序异常结束时,即WIFSIGNALED(status)返回为真时,可以使用WTERMSIG(status),来获取导致子进程结束的信号的值。一般会先用 WIFSIGNALED 来判断后才使用此宏。

4.execl()函数
int execl(const char *path, const char *arg, …);
函数参数:
path:执行的程序的路径(/home/*****/test)
可以使用相对路径或者绝对路径(听说不能识别~,未测试)
后续可变参数为执行程序的参入参数,以NULL结束,NULL作为可变参数的哨兵,表示参数的结束

execl( "./test", NULL ); //执行当前路径下的test程序。test程序无命令参数

返回值:执行成功,不返回;仅执行失败,才返回-1(注意执行的程序的名称一定要正确)

5.execlp()函数
int execlp(const char *file, const char *arg, …);
函数参数:
file:需要执行的程序名(execlp函数会到环境变量PATH设置的路径去找对应的程序名,进行执行)
函数说明:execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,最后一个参数必须用空指针(NULL)作结束

execlp("ps","ps","-a","-u","-x", NULL );//等同于执行命令:ps -aux;注意第二个参数也是程序名称和第一个参数相同
execlp("ps","ps","-aux", NULL );//命令行参数可以写在一起

返回值:执行成功,不返回;仅执行失败,才返回-1,失败原因存于errno 中(注意执行的程序的名称一定要正确)

6.dup2()函数
int dup2(int oldfd, int newfd);
函数功能:实现文件描述符的拷贝(让newfd文件描述符 指向 oldfd文件描述符 指向的文件)
函数参数:int型的文件描述符(open()函数打开文件,返回的就是int型的文件描述符;open是系统函数),而不是FILE 类型的文件指针(FILE *是fopen打开的文件;fopen是库函数)
返回值:调用成功则返回新的文件描述符,出错则返回-1
实现重定向功能:

fd = open("./test.txt",O_CREAT|O_RDWR, S_IRWXU );  // 原型:int open(const char *pathname, int flags, mode_t mode)
dup2(fd, STDOUT_FILENO); //将STDOUT_FILENO文件描述符 指向 fd文件描述符 指向的文件;即将标准输出 重定向到fd指向的文件
printf("hahahahaha");
close(fd);
//该程序就能将hahahha写在指定的test.txt文件中了

备注:
STDOUT_FILENO、STDIN_FILENO是int型的文件描述符,是非负整数,属于没有buffer的I/O;一般定义为0, 1, 2 … 1024 直接调用系统调用,在<unistd.h>。
open()系统函数,返回的是目前未被占用最小文件描述符
文件描述符对应的函数是open() read() write() close()等;

stdout stdin stderr 是FILE 类型的文件指针;属于标准I/O,在<stdio.h>。
所以可以使用:fprintf(stdout, “hahahah”);
fopen()库函数,返回的是FILE 类型的文件指针
FILE类型的文件指针,对应的函数是 fopen() fgets() fputs() fprintf() fclose() fgetc() fputc()等

僵尸进程和孤儿进程的概念:

子进程结束后,其使用的内存资源(如:堆栈资源等)会被销毁。但是其在内存中的进程资源(PCB进程控制块)会残留,只有等待父进程进行回收,并将子进程的进程资源进行销毁。

僵尸进程:
子进程已经结束,但是父进程未结束,且父进程未回收子进程状态。
子进程结束后,到父进程回收子进程前,该子进程状态称为僵尸态。
僵尸进程不能使用kill -9 pid 杀掉。因为本来就是结束状态了。只能通过将父进程杀掉,然后该子进程资源就会被系统init进程回收。

ps -ef | grep defunct —查看系统僵尸进程

孤儿进程:
子进程未结束,但父进程已结束。该子进程会被系统init进程进行托管,init将成为该子进程的父进程,等其结束后,进行资源的回收等。
init进程,pid=1(这是系统级的),用户级的init进程的pid不确定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值