一、进程ID

进程ID即是进程标识,每一个进程都会有一个唯一的非负整数来作为它的进程ID。

ID为0的进程通常是调度进程,也可称为交换进程,该进程是内核的一部分,不执行硬盘上的程序,因此也被称为系统进程。

ID为1的进程通常是init进程,init通常读取与系统有关的初始化文件,,并将系统引导到一个状态。init进程绝不会终止,它是一个普通的用户进程,但是它以超级用户特权运行,init会称为所以孤儿进程的父进程。

进程ID可以由以下函数获得

 #include <unistd.h>

 pid_t    getpid(void);                //返回值:调用进程的进程ID
pid_t getppid(void); //返回值:调用进程的父进程ID
uid_t getuid(void); //返回值:调用进程的实际用户ID
uid_t geteuid(void); //返回值:调用进程的有效用户ID
gid_t getgid(void); //返回值:调用进程的实际组ID
gid_t getegid(void); //返回值:调用进程的有效组ID

二、函数fork

#include  <unistd.h>

pid_t     fork(void);        //返回值:子进程返回0,父进程返回子进程的进程ID,失败返回-1

fork函数执行成功时会返回两次,一次在父进程中返回子进程的进程ID,一次在子进程中返回0,因此可以在此使用if语句作为父子进程的分支。子进程是父进程的副本,共享的只有代码段,子进程的堆、栈、全局段、静态数据段都是父进程的副本,是在创建在子进程时拷贝的。

fork之后父进程和子进程的执行先后是不确定的,这取决于内核所使用的调度算法。

文件共享

父进程和子进程之间打开的文件是共享的,原理是子进程使用了从父进程拷贝的文件标识符,使得它们可以访问同一个文件,另外,它们共享同一个文件偏移量

三、函数vfork

#include <unistd.h>

pid_t    vfork(void) ;       //返回值:子进程返回0,父进程返回子进程的进程ID,失败返回-1

vfork函数同样用于创建一个子进程,但是它与fork不同的是,vfok创建的新进程的目的是加载(exec)一个新程序。vfork调用后,会保证子程序的先运行,知道它调用exec或exit父程序才会被调度运行(如果子进程在此过程中需要父进程的进一步动作,会导致程序锁死)

四、进程的终止

进程有五种正常终止和三种异常终止方式,这里不一一阐述,主要说明以下一种。

调用exit函数

exit函数由ISO C定义,其操作包括调用各终止处理程序,然后关闭I/O流等

其中终止处理程序由函数atexit和on_exit登记

#include <stdlib.h>

int atexit(void (*function)(void));   //funtion:需要进行终止处理的函数指针,返回值:成功返回0

int on_exit(void (*function)(int stats, void * arg), void *arg);  //funtion:于atexit不同的是,该函数可得到exit的参数,即,能够知道程序是在什么状态下终止的

五、函数wait和waitpid

这两个函数的作用是等待子进程终止,它们的函数定义如下

#include <sys/wait.h>

pid_t  wait(int *statloc);
//statloc: 用于接收子进程的结束状态
//返回值:子进程进程号 pid_t waitpid(pid_t pid, int *statloc, int option);
/* statloc:同上
pid:    == -1 功能与wait类似,pid就无意义了
      == 0 等待组id等于pid的进程组中任意进程结束。
      < -1 等待组id是pid的绝对值的任意进程结束
      > 0 等待进程号是pid的进程结束 options 0 :以阻塞状态等待子进程结束
WNOHANG 如果没有子进程结束会立即返回
WUNTRACED 等待的进程处于停止状态,并且之前,没有报告过,则立即返回
返回值:子进程的进程号
*/

在一个子进程 终止前,wait使其调用者阻塞,而waitpid可以使调用者不阻塞

waitpid可以控制等待指定的某个子进程

如果子进程在wait调用前就已终止,wait会立即返回并取得该子进程的状态,否则wait使调用者阻塞

当一个进程终止时,内核就会向它的父进程发送一个SIGCHLD信号。父进程可以在信号处理函数中用wait接收到子进程的结束状态,进行一些相应操作,可以大大增加程序运行效率。

六、函数exec

使用fork函数或vfork能够创建新的子进程,子进程调用exec后可以执行另一个程序,新程序从main函数开始执行,因为调用exec不创建新的进程,只是将子进程替换为新的程序,所以前后进程ID并不改变

exec函数有以下几种:

#include <unistd.h>

    int execl(const char *path, const char *arg, ...);
path:可执行文件的路径+名字
arg:给可执行文件的参数,类似于命令行参数,必须以NULL结尾,第一个必须是可执行文件名。 int execlp(const char *file, const char *arg, ...);
file:可执行文件的文件名,会从PATH环境变量指定的位置找可执行文件 int execle(const char *path, const char *arg,..., char * const envp[]);
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[]); int fexecve(int fd, char *const argv[], char *const envp[]);

七、函数fork与vfork区别

fork函数

使用fork函数创建的子进程,会将父进程的数据段、堆栈复制,与父进程共享代码段。

vfork函数

vfork函数的调用通常是为了创建新进程来exec一个新程序,vfork不会将父进程的地址空间完全复制到子进程中,vfork函数创建的子进程在调用exec和exitz之前,它会在完全运行在父进程的地址空间上,vfork会保证子程序的先运行,直到调用exec和exit之后父进程才有可能被调度运行。

使用vfork和fork创建子进程都能够调用exec产生新的程序,然而vfork函数不会对父进程的地址空间进行复制,通过使用vfork可以减少不必要的开销

UNIX环境C语言进程控制的更多相关文章

  1. UNIX环境高级编程——进程控制

    一.进程标识符 ID为0的进程是调度进程,常常被称为交换进程.该进程是内核的一部分,它并不执行任何磁盘上的程序,因此也被称为系统进程.进程ID 1通常是init进程,在自举过程结束时由内核调用.ini ...

  2. UNIX环境C语言进程通信

    一.信号管理 1.函数signal signal函数是UNIX系统信号机制最简单的接口 #include <signal.h> typedef void (*sighandler_t)(i ...

  3. Unix环境高级编程—进程控制(二)

    一.函数wait和waitpid 今天我们继续通过昨天那个死爹死儿子的故事来讲(便于记忆),现在看看wait和waitpid函数. #include<sys/wait.h> pid_t w ...

  4. unix环境高级编程----进程控制wait()

    一.wait()函数 当一个进程中调用wait()函数的时候 (1)假设其全部的子程序都还在执行,则堵塞 (2)假设一个子进程已终止.则等待父进程获取其终止状态. (3)假设没有子进程,则返回错误. ...

  5. Unix环境高级编程—进程控制(三)

    一.解释器文件 解释器文件属于文本文件,起始行形式为: #! pathname[optional-argument] 我们创建一个只有一行的文件如下: #!/home/webber/test/echo ...

  6. 【linux草鞋应用编程系列】_2_ 环境变量和进程控制

    一. 环境变量     应用程序在执行的时候,可能需要获取系统的环境变量,从而执行一些相应的操作.     在linux中有两种方法获取环境变量,分述如下.   1.通过main函数的参数获取环境变量 ...

  7. UNIX环境高级编程——进程管理和通信(总结)

    进程管理与通信 进程的管理 进程和程序的区别: 进程: 程序的一次执行过程   动态过程,进程的状态属性会发生变化 程序:存放在磁盘上的指令.数据的有序集合  是个文件,可直观看到 程序program ...

  8. UNIX环境高级编程——进程基本概述

    一.什么是进程 从用户的角度来看进程是程序的一次执行过程.从操作系统的核心来看,进程是操作系统分配的内存.CPU时间片等资源的基本单位.进程是资源分配的最小单位.每一个进程都有自己独立的地址空间与执行 ...

  9. UNIX环境高级编程——进程关系

    一.终端的概念 在UNIX系统中,用户通过终端登录系统后得到一个Shell进程,这个终端成为Shell进程的控制终端(Controlling Terminal),控制终端是保存在PCB中的信息,而我们 ...

随机推荐

  1. 根据select中选定option触发不同事件

    做公司项目,要实现一个小需求,根据下拉框选定的数据,绑定不同的事件.我的思路是获取select下面的option值,然后给它们定义不同的点击事件,但是在使用中option不能添加类,同时没有click ...

  2. PlSqlDev中执行INSERT SQL语句包含&符号导致数据异常

    在PLSQL Developer中执行Insert语句时提示如下信息: 当时未注意,直接点击OK按钮继续. 导入数据后查看发现部分数据中的参数丢失了一部分,呈以下规律: . 而正常应为: . 经询问大 ...

  3. springMVC-上传图片

    SpringMVC文件上传与下载 上传图片 配置多媒体文件解析器 配置虚拟目录 在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加: <Context doc ...

  4. Elasticsearch之探索集群信息

    REST API 启动并运行了节点和集群,下一步是了解如何与它进行通信.elasticsearch提供了一个非常全面和强大的REST API,可以使用它与集群进行交付. 使用API完成以下: • 检查 ...

  5. 转 sqlplus 设置回闪 sqlplus下使用退格backspace回删出现^H的解决办法

    转自 http://blog.csdn.net/chinadm123/article/details/44099351 1.进入sqlplus前设置回删 在进入sqlplus之前,在当前termina ...

  6. Unity Shader入门精要学习笔记 - 第17章 Unity的表面着色器探秘

    转自 冯乐乐的<Unity Shader 入门精要> 2010年的Unity 3 中,Surface Shader 出现了. 表面着色器的一个例子. 我们先做如下准备工作. 1)新建一个场 ...

  7. P1281 书的复制

    题目描述 现在要把m本有顺序的书分给k给人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一.第三.第四本书给同一个人抄写. ...

  8. kafka-->storm-->mongodb

    目的: 通过Spout发射kafka的数据,到bolt统计每一个单词的个数,将这些记录更新到mongodb中. Spout的nextTuple方法会一直处于一个while循环这中,每一条数据发送给bo ...

  9. python经典一百道习题(转自奶酪博客)

    无论学习哪门计算机语言,只要把100例中绝大部分题目都做一遍,就基本掌握该语言的语法了. [程序1] 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? #Filena ...

  10. Xcode 升级后,cocoaPod 问题

    当我从Xcode 6.3切换到Xcode6.4的时候,因为我是mac上安装了两个不同的版本,现在把Xcode 6.3卸掉了. 现在再次运行pod install命令的时候,提示如下错误:   Upda ...