进程函数

简单描述一下关于进程的函数,主要有fork调用、exec调用、exit调用、wait调用和sleep调用。

fork调用

所需头文件

#include <unistd.h>     //标准函数库

#include <sys/types.h>  //提供系统调用的标志

函数原型

pid_t fork(void);  //创建子进程时,复制父进程上下文

pid_t vfork(void);  //创建子进程时,不复制父进程上下文

返回值

成功:返回两个值。子进程返回0,父进程返回子进程ID。

失败:-1

fork函数是Unix/Linux操作系统中用于创建子进程的函数。当调用fork()函数时,操作系统会创建一个与原进程几乎完全相同的新进程。

  • 操作系统接收到fork()函数调用后,会复制父进程的所有资源(包括代码、数据、堆栈等)到子进程。
  • 子进程拥有与父进程完全相同的内存映像,但是具有独立的地址空间。
  • 子进程从fork()函数的返回处开始执行,而父进程则继续在原来的位置执行。
  • fork()函数返回两次,一次返回给父进程,一次返回给子进程。在父进程中,fork()函数返回子进程的PID;在子进程中,fork()函数返回0。
  • 父进程和子进程是相互独立的,它们有不同的PID,但是它们共享相同的代码段、数据段和堆栈段。
  • 父进程可以通过获取子进程的PID,并使用系统调用wait()等待子进程的结束,从而获得子进程的返回状态。而子进程可以通过系统调用exec()来执行新的程序,从而创建一个全新的进程。
 1 #include <sys/types.h>      //提供系统调用的标志   
 2 #include <sys/stat.h>       //提供系统状态信息和相关函数
 3 #include <sys/uio.h>        //提供进程I/O操作的相关函数
 4 #include <unistd.h>         //标准函数库
 5 #include <fcntl.h>          //文件操作相关函数库
 6 #include <string.h>    
 7 #include <sys/wait.h>  
 8 #include <stdio.h>
 9 #include <stdlib.h>
10 
11 int main(int argc, char **argv)
12 {
13     char buf[100] = {0};
14     pid_t pid;
15     int fd, status;
16      
17     if( (fd = open("temp", O_CREAT | O_RDWR| O_TRUNC, 0666)) == -1 ){
18         perror("创建文件");
19         exit(1);
20     }
21     
22     strcpy(buf, "父进程数据");
23     if( (pid = fork()) == 0 ){
24         strcpy(buf, "子进程数据:");
25         puts("子进程正在工作");
26         printf("子进程PID是%dn", getpid());
27         printf("父进程PID是%dnn", getppid());
28         write(fd, buf, strlen(buf));
29         close(fd);
30         exit(0);
31     }else{
32         puts("父进程正在工作:");
33         printf("父进程PID是%dn", getpid());
34         printf("子进程PID是%dnn", pid);
35         write(fd, buf, strlen(buf));
36         close(fd);
37     }
38     wait(&status);
39     return 0;
40 }

代码运行结果

由结果而知,父进程输出信息,然后调用子进程后等待子进程结束;父进程调用子进程后,父进程由内核状态转为用户状态,子进程开始执行并输出信息。然后子进程调用exit()函数进入僵死状态。父进程由用户状态重新回到内核状态并结束父进程。

 

exec调用

所需头文件

#include <unistd.h>     //标准函数库

函数原型

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execv(const char *path, const * const argv[]);

int execve(const char *path, char *const argv[], char *const envp[]);

int execvp(const char *file, char *const argv[]);

返回值

成功:不返回

失败:-1

exec函数以新进程代替原进程,但PID保持不变,因此exec系统调用实际上没有创建新进程,只是用一个全新的程序替了当前进程的代码、数据、堆栈。

 

exit调用

所需头文件

#include <unistd.h>     //标准函数库

#include <stdlib.h>

函数原型

void exit(int status);             //合适时释放

void _exit(int status);           //立即释放

返回值

不返回

exit和_exit系统调用都是用于终止一个进程。(exit比较安全)

系统调用exit()将进行一些上下文清理工作,例如关闭文件描述符、释放所有占用的资源、清空缓冲区等。进程执行exit系统调用后,linux内核将删除进程的上下文,但保留进程表项,进程处于僵死态。等待父进程回收资源,再删除进程表项的内容,释放进程PID。

系统调用_exit()立即终止发出调用的进程,不会刷新输入输出缓冲区(因此进程结束前必须自己刷新缓冲区,或改用exit()系统调用)。所有属于该进程的文件描述符都关闭。如果该进程拥有子进程,那么父子进程关系被转到init进程上。被结束的进程将收到来自子进程的僵死信号SIGCHLD。如果被结束的进程在控制台或终端上运行,shell程序将收到SIGHUP信号。参数status是返回给父进程的状态值,父进程可通过wait系统调用获得。status只有最低1个字节能被父进程读取(实际值范围:0~255)

 

wait调用

//所需头文件
#include <sys/wait.h>
//函数原型
pid_t wait(int *status);
//返回值
成功:退出的子进程PID
失败:-1
    //处理子进程退出状态值的宏
    WIFEXITED(status):如果子进程正常退出,则该宏为真
    WEXITSTATUSA(status):如果子进程正常退出,则该宏获取子进程的退出值

wait调用用于父进程等待子进程的终止(阻塞当前进程,直到子进程终止),如果当前进程没有子进程,会立即返回一个错误。

 

sleep调用

//所需头文件
#include <unistd.h>
//函数原型
unsigned int
//返回值

sleep调用用于使进程主动进入睡眠状态。

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/couvrir/p/17609976.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!