博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux系统编程:进程控制
阅读量:4932 次
发布时间:2019-06-11

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

一、进程相关操作与编程对应函数

1.进程创建:两种方式来实现。

①fork:创建一个子进程,父子进程共享一份代码程序,但是各有一份独立的数据,为了效率和保持数据的独立采用写时复制技术(COW)。运行无优先级。

#include 
pid_t fork(void);

返回值:成功——子进程(0),父进程(子进程pid)、失败——(-1)

②vfork:创建一个新进程,子进程复制一份父进程的数据和堆栈空间(COW技术),继承父进程的用户代码、用户组、环境变量、打开的文件等资源,但是子进程不会继承父进程的文件锁定和未处理的信号。子进程优先执行,直到子进程调用exec函数或退出。在调用exec或exit之前,子进程和父进程的数据是共享的。

#include
pid_t vfork(void);

返回值:成功——子进程(0),父进程(子进程pid)、失败——(-1)

2.进程等待

①wait:直到有信号来到或所有子进程结束时父进程才恢复执行。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值status。

#include
#include
pid_t wait (int * status);

返回值:成功——子进程PID,失败——(-1)

②waitpid:指定等待的进程。

#include
#include
pid_t waitpid(pid_t pid,int * status,int options);
Pid:欲等待的子进程识别码    pid <-1 等待进程组识别码为pid绝对值的任何子进程。    pid =-1 等待任何子进程,相当于wait()。    pid = 0 等待进程组识别码与目前进程相同的任何子进程。    pid > 0 等待任何子进程识别码为pid的子进程options 通常设置成0
参数解释

返回值:成功——子进程PID,失败——(-1)

3.执行程序

①exec函数族:在当前的进程中执行任务。

主要函数:execl、execv 、execle 、execve 、execlp 、execvp。函数的主要区别在于参数传递方式的不同

"l" : list,函数的参数是通过一一列举的方式来传递的"v" : vector,向量、指针的意思,参数是通过字符数组指针来传递"e" : environment"p" : PACH,指定文件默认从PATH 环境变量中查找文件并执行
函数字母含义
#include
/* *执行参数path字符串所代表的文件路径,接下来的参数,代表执行该文件时传递过去的argv(0)、argv[1]……,最后一个参,数必须用空指针(NULL)作结束。*/int execl(const char *path,const char *arg,...);/* *执行参数path字符串所代表的文件路径,与execl()不同的地方在于execv()只需两个参数,第二个参数利用数组指针来传递给执行文件, char *const argv[]是指针数组,argv[0]、argv[1]...存放的是字符串的起始地址,这里要求他的最后一个成员存放的是NULL*/int execv(const char *path,char *const argv[]);//从PATH环境变量指定的目录中查找符合file指针指向的字符串的文件来执行int execlp(const char *file,const char *arg,...);int execle(const char *path,const char *arg,...,char *const envp[]);int execve(const char *path,char *const argv[],char *const envp[]);int execvp(const char *file,char *const argv[]);
函数用法解析

返回值:失败——(-1)

const char *argv[]={"ps","-au",NULL};const char *envp[]={"PATH=/bin/:/usr/bin:usr/local/bin","HOME=/home/clbiao/arm",NULL};//执行文件位置在第一个参数,执行参数在后面指出execl("/bin/ps","ps","-au",NULL);execv("/bin/ps",argv);//指定参数并指定搜索位置execve("/bin/ps",argv,envp);execle("/bin/ps","ps","-aux",NULL,envp);//只指定参数,从系统默认的PATH中搜,不用自己去定义envpexecvp("ps",argv); execlp("ps","ps","-au",0);
识记方法

②system函数:在当前进程再创建一个进程来执行任务,是对fork、exec、waitpid的进一步封装。

#include 
int system(const char *cmdstring);

4.进程终止

①exit:退出进程前检查文件的打开情况,把打开的文件写回

#include 
void exit(int status);

②_exit:直接退出进程,不处理标准I/O缓冲区

#include 
void _exit(int status);//status是返回给父进程的状态

二、演示程序

1 #include 
2 #include
3 #include
4 int main() 5 { 6 int pid; 7 pid = vfork(); 8 //pid = fork(); 9 if(pid==0)10 {11 printf("\nChild process\n");12 printf("This is in output buffer A");13 _exit(0);14 }15 else16 {17 printf("\nFather process\n");18 printf("This is in output buffer B");19 exit(0);20 }21 }
Test Code
//使用vfork时是:Child processThis is in output buffer AFather processThis is in output buffer B//使用fork时是:Child processFather processThis is in output buffer B
运行结果

结果分析:

    使用vfork时,子进程先执行,“Child process”先打印出来,接着把“This is in output buffer B”写到printfbuffer,并没有打印出来,因为后面的_exit(0)直接忽略I/O缓冲区,不作任何处理。然而轮到父进程执行时,继续接着往printfbuffer里面写数据(因为父子共用进程空间)直到遇到“\n”,进行处理,所以还是会把之前子进程残留在缓冲区的数据写出来。使用fork时,父子独立的进程空即数据区,子进程执行到_exit()buffer没有打印出来的字符就放在那里不管了,一点都不负责任exit()就不同了,虽然buffer里面的字符串中没有"\n",但是他在退出之前还是收拾了这个烂摊子 (注:printf函数把缓冲区中的数据打印出来的条件是遇到"\n"换行符)

三、问题思考

问1.什么情况下会导致vfork出来的进程死锁?

答1.在子进程调用exec或exit之前,子进程的进一步运行要依赖于父进程的一些操作就会导致死锁

 

转载于:https://www.cnblogs.com/lubiao/p/4732862.html

你可能感兴趣的文章
创建 overlay 网络 - 每天5分钟玩转 Docker 容器技术(50)
查看>>
一些简单的SQL Server服务器监控
查看>>
MongoDB的Windows安装
查看>>
什么是函数式编程(副作用、纯函数、引用透明)
查看>>
android系统提供的几种颜色Color
查看>>
【OpenCV学习笔记】三十、轮廓特征属性及应用(七)—位置关系及轮廓匹配
查看>>
selenide01---截图
查看>>
mysql 查询死锁语句
查看>>
pl_sql操作--激活提升权限scott用户
查看>>
UDP网络编程
查看>>
[Nuxt] Display Vuex Data Differently in Each Page of Nuxt and Vue.js
查看>>
[Ramda] Curry and Uncurry Functions with Ramda
查看>>
[TypeScript] Function Overloads in Typescript
查看>>
[React] React Fundamentals: Mixins
查看>>
关于SQL数据库 数据库名 表名的一些操作
查看>>
1013. 识别三角形
查看>>
IE8+兼容经验小结
查看>>
Android studio下使用SharedSDK
查看>>
会话与请求
查看>>
hibernate one2many (单向关联)
查看>>