【Linux&Unix--exec 与 fock 系统调用】

个人学习整理,如有不足之处,请不吝指教。转载请注明:@CSU-Max

系列博文:

Linux&Unix学习第一弹 —— 文件描述符与权限 

 Linux&Unix学习第二弹
-- 文件描述符与权限

进程和程序

简单的说,进程与应用程序的区别在于应用程序作为一个静态文件存储在计算机系统的硬盘等存储空间中,而进程则是处于动态条件下由操作系统维护的系统资源管理实体。

(1)进程更能真实地描述并发,而程序不能。

(2)进程由程序和数据两部分组成,进程是竞争计算机系统有限资源的基本单位,也是进程处理机调度的基本单位。

(3)程序是静态的概念;进程是程序在处理机上一次执行的过程,是动态的概念。

(4)进程有生存周期,有诞生有消亡。是短暂的;而程序是相对长久的。

(5)一个程序可以作为多个进程的运行程序;一个进程也可以运行多个程序。

(6)进程具有创建其他进程的功能;而程序没有。

exec和fock简述

exec系统调用从指定程序重新初始化进程,虽然进程还在,但程序已经改变了。

fock系统调用仅通过复制指令、用户数据和系统数据段来创建从现存进程克隆的新进程,该新进程不是从程序初始化得来的,所以旧进程和新进程执行同样的指令。

除启动UNIX内核本身外,exec是程序在UNIX上获得执行的唯一方法,不仅shell使用exec执行程序,而且shell和其祖先shell也会被exec调用。fock是创建新进程的唯一方式。

详解exec系统调用

事实上,并没有叫做“exec ”的系统调用,所谓的“ exec ”系统调用实际上是6个以execAB形式命名的系统调用,其搭配方式如下图所示:

这里的A可以为 l 或 v ,这取决于参数是直接在调用(列表)中,还是在数组(向量)中;B要么没有,要么为 p ,p 表示使用 PATH 环境变量查找程序,要么为 e ,e 表示使用特定环境。(用户不能在同一调用中同时获得特征 p 和 e 。因此,这6个调用分别为execl,execv,
execlp, execvp, execle, execve。

函数原型及解释

//execl -- 执行带参数列表的文件
int execl(
	const char *path,	/*program pathname*/
	const char *arg0,	/*first arg (file name)*/
	const char *arg1,	/*second arg (if needed)*/
	. . . ,
	(char *) NULL		/*arg list terminator*/
);

path参数是一个可由有效用户ID(比如说模式755)执行的程序文件路径名,该可执行程序的内容要正确。

path 参数后面的一组参数收入到一个字符指针数组,且最后一个参数的值为NULL,用来停止收入和终止数组,这组参数的第一个都是程序文件的名字(并不是整个路径)。

通过重新初始化栈,来自程序的指令覆盖了进程的指令段,并且来自程序的数据也覆盖了进程的用户数据,然后进程从顶端执行该新程序(也就是说,调用了它的 mian 函数)。

其他5个 exec 系统调用

//execv -- 执行带参数向量的文件
int execv(
	const char *path,	/*program pathname*/
	char *const argv[]	/*argument vector*/
);

//execlp -- 执行带参数列表和路径搜索的文件
int execlp(
	const char *file,	/*program file name*/
	const char *arg0,	/*first arg (file name)*/
	const char *arg1,	/*second arg (if needed)*/
	. . . ,
	(char *) NULL		/*arg list terminator*/
);

//execvp -- 执行带参数向量和路径搜索的文件
int execvp(
	const char *file,	/*program file name*/
	char *const argv[]	/*argument vector*/
);

//execle -- 执行带参数列表和环境变量的文件
int execle(
	const char *path,	/*program pathname*/
	const char *arg0,	/*first arg (file name)*/
	const char *arg1,	/*second arg (if needed)*/
	. . . ,
	(char *) NULL		/*arg list terminator*/
	char *const envv[]	/*environment vector*/
);

//execve -- 执行带参数向量和环境变量的文件
int execve(
	const char *path,	/*program pathname*/
	char *const argv[]	/*argument vector*/
	char *const envv[]	/*environment vector*/
);

注意一下 execlp 和 execvp ,由前面的介绍可知,当B为 p 时,表示使用 PATH 环境变量查找程序,下面让我们来简单的看一下。

若 execlp 或 execvp 的 file 参数没有斜线,则把PATH环境变量中所列出的字符串一个一个与之比较,直到定位到一个带有结果路径名的普通文件,其中结果路径名具有执行权限。

情况一:如果这个文件包含一个可执行程序(在它的第一个字处由一个代码号指示的),便执行它;

情况二:如果不包含一个程序,则将其假定为一个脚本文件,通常为了运行这个脚本文件,都把路径作为shell的第一个参数来执行shell。

如果 PATH 查找的结果证明没有任何内容是可在执行的,则 exec 失败。

若 file 参数中有“ / ”,就不用进行查找,即认为完成了路径查找,但是它仍然可能是一个脚本文件。

详解fock系统调用

在某种程度上,我们可以将 fock与 exec 看作是相反的:fock 可以创建一个新进程,但它并不初始化新程序中的这个进程,相反,新进程的指令、用户数据段和系统数据段几乎就是旧进程的完全复制。

函数原型及解释

//fock -- 创建新进程
pid_t fock(void);

fock调用返回后,两个进程(子进程和父进程)都接收返回值,但返回值是不同的,父进程将接受子进程的进程ID,而子进程接收到的返回值为0.返回 -1 表示出错,但是由于 fock 没有参数,所以极少出错,引发错误的唯一原因便是资源耗尽,如交换空间不足或执行了太多的进程。

当调用 fock 成功后,一般子进程接着执行exec ,而父进程要么等待子进程终止,要么离开去做其他的事情。

fock调用下的父进程与子进程

fork创建的子进程继承了父进程的大部分属性,因为它的系统数据段是从父进程复制而来的。但是也有极少属性没有得到继承:子进程ID与父进程ID是不同的,它们是不同的进程;若父进程正在运行多线程,那么只有执行 fock 的那个线程会存在与子进程中,父进程中的多个线程不会受到什么影响;子进程的累计执行时间会被重置为零,因为它处在生命期的开始。

***************************************************************************

*  转载请注明出处:  @CSU-Max   http://blog.csdn.net/csu_max 
    *

***************************************************************************

【Linux&Unix--exec 与 fock 系统调用】,布布扣,bubuko.com

时间: 2024-11-05 02:40:50

【Linux&Unix--exec 与 fock 系统调用】的相关文章

【Linux&Unix--open/close/write/read系统调用】

个人学习整理,如有不足之处,请不吝指教.转载请注明:@CSU-Max 系列博文: Linux&Unix学习第一弹 -- 文件描述符与权限  Linux&Unix学习第二弹 -- exec 与 fock 系统调用 Linux&Unix学习第三弹 -- open/close/write/read系统调用 在 Unix/Linux 系统中,文件是一个很重要的概念,本文将介绍 Linux 中和文件相关的几个重要的系统调用--open-close-write-read 系统调用. open系

在Linux使用exec执行命令时报的哪些错

问题1:find: paths must precede expression [[email protected] data]# find /oracle/backup/exp/data -name exp_table01_db01_*.dmp.gz -atime +2 exec rm -rf {}\;find: paths must precede expression: exp_table01_db01_20170928235039.dmp.gz 描述:在执行find命令时,在查找的内容必

Linux/Unix C编程之的perror函数,strerror函数,errno

#include <stdio.h> // void perror(const char *msg); #include <string.h> // char *strerror(int errnum); #include <errno.h> //errno ? errno 是错误代码,在 errno.h头文件中: perror是错误输出函数,输出格式为:msg:errno对应的错误信息(加上一个换行符): strerror?是通过参数 errnum (就是errno)

linux/unix man用法

最近开始学习linux c编程,需要用到很多库函数和c标准库函数,发现原来man命令还可以用来查询函数原型. 比如输入man lseek可以获取函数lseek的原型和所属头文件. 有些函数名既是linux命令又是系统调用,如mkdir,可以输入man 2 mkdir获取该函数原型.只输入man mkdir获取的是命令mkdir的帮助. 对于库函数可以输入man 3 <库函数名>  获得帮助信息.man 3 opendir 对于系统开发经常需要查询函数还是非常方便的,另外在vim中可以用shif

Linux/UNIX线程控制

线程控制 线程属性 调用pthread_create函数的例子中,传入的参数都是空指针,而不是指向pthread_attr_t结果的指针.可以用pthread_attr_t结构修改线程默认属性,并把这些属性与创建的线程联系起来.可以使用pthread_attr_init函数初始化pthreaad_attr_t结构.调用pthread_attr_init以后,pthread_attr_t结构所包含的内容就是操作系统实现支持的线程所有属性的默认值.如果要修改其中个别属性的值,需要调用其他的函数.pt

Linux/Unix shell 监控Oracle监听器(monitor listener)

使用shell脚本实现对Oracle数据库的监控与管理将大大简化DBA的工作负担,如常见的对实例的监控,监听的监控,告警日志的监控,以及数据库的备份,AWR report的自动邮件等.本文给出Linux 下使用 shell 脚本来监控 Oracle 监听器. Linux Shell的相关参考:        Linux/Unix shell 脚本中调用SQL,RMAN脚本        Linux/Unix shell sql 之间传递变量        Linux/Unix shell 调用

Linux/Unix shell 自动发送AWR report(二)

观察Oracle数据库性能,Oracle自带的awr 功能为我们提供了一个近乎完美的解决方案,通过awr特性我们可以随时从数据库提取awr报告.不过awrrpt.sql脚本执行时需要我们提供一些交互信息,因此可以将其整合到shell脚本中来实现自动产生指定时段的awr报告并发送给相关人员.本文对Linux/Unix shell 自动发送AWR report的功能进行了完善和补充. 1.shell脚本 [python] view plain copy print? [email protected

《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)

<Linux/Unix系统编程手册>读书笔记 目录 第11章 这章主要讲了关于Linux和UNIX的系统资源的限制. 关于限制都存在一个最小值,这些最小值为<limits.h>文件中的常量. 通过cat 命令查看: [email protected]:~/Code/tlpi$ cat /usr/include/limits.h /* Copyright (C) 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2005 Free Software

《Linux/Unix系统编程手册》读书笔记8 (文件I/O缓冲)

<Linux/Unix系统编程手册>读书笔记 目录 第13章 这章主要将了关于文件I/O的缓冲. 系统I/O调用(即内核)和C语言标准库I/O函数(即stdio函数)在对磁盘进行操作的时候都会发生缓冲.通过缓冲可以在一定程度上将用户空间与实际的物理设备分离,还可以减少内核访问磁盘的次数. 先来看看关于内核缓冲区高速缓冲:read和write调用在对磁盘文件进行操作的时候不会直接访问磁盘,如下图所示. 例如:write(fd, "abc", 3) write调用会将"