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

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

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

#include <unistd.h>
pid_t fork(void);

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

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

#include<unistd.h>
pid_t vfork(void);

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

2.进程等待

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

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait (int * status);

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

②waitpid:指定等待的进程。

#include<sys/types.h>
#include<sys/wait.h>
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<unistd.h>
/*
*执行参数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中搜,不用自己去定义envp
execvp("ps",argv);
execlp("ps","ps","-au",0);

识记方法

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

#include <stdlib.h>
int system(const char *cmdstring);

4.进程终止

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

#include <stdlib.h>
void exit(int status);

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

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

二、演示程序

 #include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
int pid;
pid = vfork();
//pid = fork();
if(pid==)
{
printf("\nChild process\n");
printf("This is in output buffer A");
_exit();
}
else
{
printf("\nFather process\n");
printf("This is in output buffer B");
exit();
}
}

Test Code

//使用vfork时是:
Child process
This is in output buffer A
Father process
This is in output buffer B
//使用fork时是:
Child process
Father process
This is in output buffer B

运行结果

结果分析:

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

三、问题思考

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

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

Linux系统编程:进程控制的更多相关文章

  1. Linux系统编程@进程通信(一)

    进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...

  2. linux系统编程-进程

    进程 现实生活中 在很多的场景中的事情都是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的: 如下是一段视频,迈克杰克逊的一段视频: http://v.youku.com ...

  3. Linux系统编程@进程管理(一)

    课程目标: 构建一个基于主机系统的多客户即时通信/聊天室项目 涉及的理论知识 进程控制:僵尸进程/孤儿进程.进程控制.守护进程... 进程间通信:管道.命名管道.信号... 多线程编程: 锁.信号量. ...

  4. Linux系统编程@进程管理(二)

    1.创建守护进程(Deamon) 守护进程的概念与作用 后台服务程序 – 系统服务,进程名字往往以’d’结尾,生存周期比较长(系统装入时启动,关闭时候终止.系统装入两种启动方式:1从启动脚本.etc/ ...

  5. [linux] C语言Linux系统编程进程基本概念

    1.如果说文件是unix系统最重要的抽象概念,那么进程仅次于文件.进程是执行中的目标代码:活动的.生存的.运行的程序. 除了目标代码进程还包含数据.资源.状态以及虚拟化的计算机. 2.进程体系: 每一 ...

  6. Linux系统编程——进程替换:exec 函数族

    在 Windows 平台下,我们能够通过双击运行可运行程序,让这个可运行程序成为一个进程.而在 Linux 平台.我们能够通过 ./ 运行,让一个可运行程序成为一个进程. 可是.假设我们本来就执行着一 ...

  7. Linux系统编程—进程间同步

    我们知道,线程间同步有多种方式,比如:信号量.互斥量.读写锁,等等.那进程间如何实现同步呢?本文介绍两种方式:互斥量和文件锁. 互斥量mutex 我们已经知道了互斥量可以用于在线程间同步,但实际上,互 ...

  8. Linux系统编程-----进程fork()

    在开始之前,我们先来了解一些基本的概念: 1. 程序, 没有在运行的可执行文件 进程, 运行中的程序 2. 进程调度的方法: 按时间片轮转 先来先服务 短时间优先 按优先级别 3. 进程的状态: 就绪 ...

  9. linux系统编程之进程(一)

    今天起,开始学习linux系统编程中的另一个新的知识点----进程,在学习进程之前,有很多关于进程的概念需要了解,但是,概念是很枯燥的,也是让人很容易迷糊的,所以,先抛开这些抽象的概念,以实际编码来熟 ...

  10. 读书笔记之Linux系统编程与深入理解Linux内核

    前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...

随机推荐

  1. (广搜)聪明的打字员 -- POJ --1184

    链接: http://poj.org/problem?id=1184 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88230#probl ...

  2. mysql下的常见问题处理

    1. ubuntu中启动mysql,提示mysql access denied for user root@localhost 错误. 是因为还没有给添加的root账户配置密码信息. (1)停止mys ...

  3. 23 DesignPatterns学习笔记:C++语言实现 --- 2.5 Factory

    23 DesignPatterns学习笔记:C++语言实现 --- 2.5 Factory 2016-07-18 (www.cnblogs.com/icmzn) 模式理解   1. Flyweight ...

  4. cordova/webapp/html5 app 用corsswalk替换内核,优化安卓webview

    Crosswalk与WebView的不同 为什么要用corsswalk?由于cordova应用在安卓上运行的时候,都是调用的手机webview,而在不同的安卓机.不同版本的系统上,webview的性能 ...

  5. php autoload 笔记

    php auotload 实现了类的延迟加载机制,需要的时候在include,平时很少用到.它的实现原理搜了一下如下(不是本人研究的结果): 检查执行器全局变量函数指针autoload_func是否为 ...

  6. 咏南中间件增加HTTPS.SYS支持

    咏南中间件增加HTTPS.SYS支持 老客户可免费升级. HTTPS.SYS可以开发强大而稳定的REST SERVER. 微软在Windows Vista (server 2008) 以后使用http ...

  7. 注册一个GitHub用户的过程

    今天,我注册了一个GitHub用户.一开始,不知道GitHub是什么,还以为叫什么"getup",心里还想着什么网站名字这么奇怪,后来在舍友的帮助之下知道了原来是叫GitHub.下 ...

  8. ZooKeeper 一致性协议 ZAB 原理

    一致性协议有很多种,比如 Paxos,Raft,2PC,3PC等等,今天我们讲一种协议,ZAB 协议,该协议应该是所有一致性协议中生产环境中应用最多的了.为什么呢?因为他是为 Zookeeper 设计 ...

  9. 支付宝PC网站接口对接

    PC网站支付接口,请参考支付宝官方文档:https://b.alipay.com/signing/productSet.htm?navKey=all 1.需要提供签约账号.商户密钥 2.代码实现: 支 ...

  10. Easy前端正确删除datagrid的方式(避免直接删除索引没更新问题)

    在删除传参时,不要传索引来删除行 columns: [[ { title: '代码', field: 'Code', width: 100 }, { title: '名称', field: 'Name ...