博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
进程函数一步步理解Linux进程(2)--进程编程进程函数
阅读量:7109 次
发布时间:2019-06-28

本文共 4187 字,大约阅读时间需要 13 分钟。

查了好多资料,发现还是不全,干脆自己整理吧,至少保证在我的做法正确的,以免误导读者,也是给自己做个记录吧!

    

0. 说明

    

    

作者:Gao Peng<gaopenghigh@gmail.com>

    

本文章由Gao Peng编写,转载请注明出处。

    

原文址地:

    

    


    

1. 获得各种ID

    

    

在“一步步懂得Linux进程(1)--基础知识”中我们论讨了几种ID:PID, PPID, PGID, SID。另外Linux中还有用户ID(UID), 效有用户ID(EUID), 用户组ID(GID), 效有用户组ID(EGID)等,面下这些函数恰是用来获得这些ID:
#include 
pid_t getpid(void);pid_t getppid(void);pid_t getpgid(pid_t pid); /* pid为0时则返回用调进程的进程组ID */pid_t getsid(pid_t pid); /* pid为0时则返回用调进程的会话首进程的ID */uid_t getuid(void);uid_t geteuid(void);gid_t getgid(void);gid_t getegid(void);

    

    

2. fork函数

    

    

fork函数多是Linux中最著名的函数了。一个现有进程可以用调fork函数建创一个新进程。
#include 
pid_t fork(void);
很有意思的是,用调fork函数时,生产了子进程,而fork函数分别在父进程和子进程中都有返回,其中在父进程中返回子进程的PID,子进程中则返回0。子进程中的一切都是从父进程copy去过的(事实上,Linux用了“写时复制”的技巧,也就是指直到真正对数据生产写操纵时,这些资源才真的被copy)。fork的一个用使示例如下:
#include 
#include
int main(void) { int var = 10; pid_t pid; if ((pid = fork()) < 0) { printf("fork error\n"); } else if (pid == 0) { /* child */ printf("in child, "); var++; } else { /* parent */ printf("in parent, "); var--; } printf("pid=%d, ppid=%d, var=%d\n", getpid(), getppid(), var); return 0;}
编译并运行这个序程:
$ gcc -Wall fork_test.c$./a.outin parent, pid=21319, ppid=18586, var=9in child, pid=21320, ppid=21319, var=11
正如我们想预的那样,变量var分别在父进程和子进程中被-1和+1。

    

    


    

3. exit函数和atexit函数

    

    

3.1 exit

    

有3个函数用于畸形止终一个序程:
#include 
void exit(int status);void _Exit(int status);#include
void _exit(int status);
其中,_exit和_Exit直接进入核内,exit则是先用调执行各止终处置序程(exit handler),然后关闭全部准标IO流,最后才进入核内。三个函数中,参数status都表现止终状态。
子进程止终时,核内并没有全完抹去这个进程的一切,而是保存以必定的信息,比如PID,止终状态,用使的CPU间时总量等等。父进程可以通过wait系列函数获得到这些信息,然后再根据实际需要做更多的处置。在子进程已结束但父进程还没有去获得这些信息这段间时内,子进程叫做僵尸进程(zombie process)。
    每日一道理
今天阳光很好,坐在窗前,看窗外如此晴朗的天感觉特别舒心,雨过天晴后的世界总给人一种明媚,仿佛阳光照耀在“心田”上空,让前些天被风雨践踏的花朵重新得到爱的关怀,重现生命的活力!

    

子进程和父进程独立运行,但当子进程止终时,统系会给父进程发送一个SIGCHLD信号,父进程可以捕获这个信号并做响应的处置,但Linux中默许对次信号疏忽。

    

    

3.2 atexit

    

面前说过,exit函数会先用调执行各止终处置序程(exit handler)。这些止终处置序程,恰是通过atexit函数册注的:
#include 
int atexit(void (*func)(void));
其中,atexit的参数是一个函数址地,用调此函数时无需送传任何参数,也不期望它返回一个值。一个进程可以册注32个止终处置序程,exit用调这些函数的序顺与它们册注的序顺相反。

    


    

4. wait系列函数
4.1 wait和waitpid函数
子进程止终后,核内仍然保存该进程的一些信息,这些信息可以通过wait和waitpid函数来获得。
#include 
pid_t wait(int *statloc);pid_t waitpid(pid_t pid, int *statloc, int options);
这两个函数若执行功成则返回进程PID或者0,错出则返回-1。
执行这两个函数时,
    a. 如果其全部子进程都还在运行,则阻塞,直到有子进程止终;
    b. 如果没有子进程,则错出返回-1;
    c. 如果一个子进程已止终并等待父进程获得其止终状态,则取得其PID当即返回;
参数statloc是形整指针,当该参数不为NULL时,子进程的止终状态就存入该指针指向的元单内。
waitpid和wait的的区分是:
    a. waitpid可以等待一个指定的进程止终,所等待的进程由参数pid供给:
        pid == -1   等待任一子进程
        pid > 0     等待进程PID与pid等相的进程,若不存在,则错出返回
        pid == 0    等待PGID于等用调进程PGID的任一子进程
        pid < 0     等待其PGID于等pid绝对值的任一子进程
    b. waitpid中的第三个参数options,options可所以0,也可所以以下三个值按位“或”的结果:
        WCONTINUED  由pid指定的进程在暂停后继承,且未尚告报其状态,则返回其状态
        WNOHANG     waitpid不阻塞,返回0
        WUNTRACED   由pid指定的进程处于暂停状态,且该状态为告报过,则返回其状态
4.2 waitid函数
可以看到,waitpid函数中参数pid的用作够不纯粹,增加了代码的复杂度,降低了可读性。waitid函数与waitpid似类,但waitid用独自的参数表现要等待的子进程的类型。
#include 
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
详细用使方法可考参waitid的man手册。
4.3 wait4函数
与wait, waitpid, waitid比相,wait4函数多了一个能功:要求核内返回进程用使的资源汇总。详细可考参wait4的man手册。

5. exec系列函数

    

    

当进程用调一种exec函数时,改进程执行的序程全完替换为新序程,新序程由exec函数的参数指定。
#include 
extern char **environ;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, char *const argv[]);int execvp(const char *file, char *const argv[]);int execvpe(const char *file, char *const argv[], char *const envp[]);
可以用exec函数中的母字l, v, p, e对这6个函数做区分:
    l    表现list,要求将新序程的个每命令行参数都表现为一个独立的参数

    

    v    表现vector,与list对应,先造构一个指向全部参数的指针数组,然后把该数组址地作为参数传给exec

    

    p    表现用使file作为参数,在PATH中找寻对应的文件,file中含有"/"则视作径路

    

    e    表现可以传递一个指向境环字符串指针数组的指针,指向的字符串作为境环变量

    

    


考参资料:

    

《UNIX境环级高编程》

    

“UNIX进程揭秘” 

文章结束给大家分享下程序员的一些笑话语录: 姿势要丰富,经常上百度!

你可能感兴趣的文章
mac 安装 lightgbm 无法导入(以及解决cmake命令无法编译)
查看>>
three.js快速入门和实战
查看>>
人人都能懂的Vue源码系列—09—initEvents
查看>>
express+nginx 搭建最简单web项目
查看>>
mpvue 小程序如何自定义tabBar,不使用navigateTo跳转,模拟redirectTo跳转
查看>>
以数据库思维理解区块链
查看>>
在Laravel中使用事件记录SQL查询到日志
查看>>
ABAP Netweaver和Hybris Enterprise Commerce Platform的登录认证
查看>>
vue elementUI 表单校验(多层嵌套)
查看>>
ionic3学习之目录结构分析
查看>>
教你如何修改github上的项目语言类型
查看>>
干货 | 手把手教你快速撸一个区块链
查看>>
github fork别人项目之后,更新和提交操作
查看>>
springboot 集成 swagger2 小记
查看>>
gorose orm+dotweb框架快速构建go web网站实战(一)
查看>>
npm-发布&管理module
查看>>
JavaScript设计模式
查看>>
【Change Detection系列一】$digest 在Angular新版本中重生
查看>>
滚动相关知识点总结
查看>>
《Javascript高级程序设计 (第三版)》第三章 基本概念
查看>>