(1)exec函数说明

fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法。它可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。

(2)在Linux中使用exec函数族主要有以下两种情况

当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用任何exec 函数族让自己重生。

如果一个进程想执行另一个程序,那么它就可以调用fork函数新建一个进程,然后调用任何一个exec函数使子进程重生。

————————————————
版权声明:上面这段来自CSDN博主「guoping16」的原创文章,遵循 CC 4.0 BY-SA 版权协议,
原文链接:https://blog.csdn.net/guoping16/article/details/6583383

exec和fock简述

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

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

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

————————————————
版权声明:上面这段来自CSDN博主「方同学Max」的原创文章,
原文链接:https://blog.csdn.net/csu_max/article/details/38086223

  1. 系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。

一个进程主要包括以下几个方面的内容:

(1)一个可以执行的程序

(2) 与进程相关联的全部数据(包括变量,内存,缓冲区)

(3)程序上下文(程序计数器PC,保存程序执行的位置)

exec是一个函数簇,由6个函数组成,分别是以excl和execv打头的。

执行exec系统调用,一般都是这样,用fork()函数新建立一个进程,然后让进程去执行exec调用。我们知道,在fork()建立新进程之 后,父进各与子进程共享代码段,但数据空间是分开的,但父进程会把自己数据空间的内容copy到子进程中去,还有上下文也会copy到子进程中去。而为了 提高效率,采用一种写时copy的策略,即创建子进程的时候,并不copy父进程的地址空间,父子进程拥有共同的地址空间,只有当子进程需要写入数据时 (如向缓冲区写入数据),这时候会复制地址空间,复制缓冲区到子进程中去。从而父子进程拥有独立的地址空间。而对于fork()之后执行exec后,这种 策略能够很好的提高效率,如果一开始就copy,那么exec之后,子进程的数据会被放弃,被新的进程所代替。
总之,如果你用exec调用,首先应该fork一个新的进程,然后exec
————————————————
版权声明:上面这段来自CSDN博主「smart_yujin」的原创文章,
原文链接:https://blog.csdn.net/smart_yujin/article/details/10515247

说了很多,但自己用的时候还是没有彻底理解execve函数的运用,忘记了它的性质:系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。
来看一个例子吧:
示例代码:
要求:
编写一个多进程并发执行程序。父进 程首先创建一个执行ls命令的子进程然后再创建一个执行ps命令的子进程,并控制 ps 命令总在 ls 命令之前执行。

/*
* Function : 多进程的并发执行
*/#include "myTest1.h" int main(int argc, char *argv[]){int i;int pid1, pid2; //存放子进程号 int status1, status2; //存放子进程返回状态第二部分 操作系统算法实验 char *args1[] = { "/bin/ls","-a",NULL }; //子进程1要缺省执行的命令 char *args2[] = { "/bin/ps","-l",NULL }; //子进程2要缺省执行的命令 signal(SIGINT, (sighandler_t)sigcat); //注册一个本进程处理键盘中断的函数 pid1 = fork(); //建立子进程 1if (pid1 < 0) // 建立子进程失败? {printf("Create Process1 fail!\n");exit(EXIT_FAILURE);}if (pid1 == 0) // 子进程执行代码段 {//报告父子进程进程号 printf("I am Child1 process %d\nMy father is %d\n", getpid(), getppid());pause(); //暂停,等待键盘中断信号唤醒 //子进程1被键盘中断信号唤醒继续执行 printf("%d child1 will Running: \n", getpid()); // //装入并执行新的程序 status1 = execve(args1[0], args1, NULL);}else //父进程执行代码段 {printf("\nI am Parent process %d\n", getpid()); //报告父进程进程号 pid2 = fork();if(pid2<0){printf("Create Process2 fail!\n");exit(EXIT_FAILURE);}if (pid2 == 0) // 子进程执行代码段 {//报告父子进程进程号 printf("I am Child2 process %d\nMy father is %d\n", getpid(), getppid());//装入并执行新的程序 status2 = execve(args2[0], args2, NULL);//子进程2执行完了,唤醒子进程1/* 系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。 *///所以,下面的部分并没有执行,所以需要手动按Ctrl+C唤醒,而不是自动发信号唤醒 if (kill(pid1, SIGINT) == 0)printf("%d Wakeup  its brother %d.\n", getpid(), pid1);else printf("%d send signal failed.\n", getpid());}}waitpid(pid2, &status2, 0); //等待子进程结束printf("\nMy child2 exit! status = %d\n\n", status2);waitpid(pid1, &status1, 0); //等待子进程结束printf("\nMy child1 exit! status = %d\n\n", status1);return EXIT_SUCCESS;}

头文件:

#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
//进程自定义的键盘中断信号处理函数
typedef void (*sighandler_t) (int);
void sigcat()
{printf("%d Process continue\n",getpid());
}

linux系统中执行上面的代码后,发现子进程2中用execve执行ps命令后,并没有发送信号给子进程1,既没有提示信号发送成功,也没有提示信号未发送成功,而是子进程2中execve下面的代码好像直接给忽略了,没有执行。所以,子进程1 pause()之后,需要我们手动发送信号,按下Crtl+C去唤醒Child 1.
关于信号,参考:https://www.cnblogs.com/nufangrensheng/p/3514157.html

信号:SIGINT 由Interrupt Key产生,通常是CTRL+C或者DELETE。

正确的代码:应该是child 2中execve之后不要再有任何代码(这时它们属于原进程的代码),即使有,也被执行execve时载入的进程的新代码替代掉了,不会执行。
正确方法应该是,父进程等待子进程2执行完毕,并且在父进程中把子进程1唤醒,子进程1继续执行完毕。
如下:(头文件仍旧不变)

/*
* Function : 多进程的并发执行
*/#include "myTest1.h" int main(int argc, char *argv[]){int i;int pid1, pid2; //存放子进程号 int status1, status2; //存放子进程返回状态第二部分 操作系统算法实验 char *args1[] = { "/bin/ls","-a",NULL }; //子进程1要缺省执行的命令 char *args2[] = { "/bin/ps","-l",NULL }; //子进程2要缺省执行的命令 signal(SIGINT, (sighandler_t)sigcat); //注册一个本进程处理键盘中断的函数 pid1 = fork(); //建立子进程 1if (pid1 < 0) // 建立子进程失败? {printf("Create Process1 fail!\n");exit(EXIT_FAILURE);}if (pid1 == 0) // 子进程执行代码段 {//报告父子进程进程号 printf("I am Child1 process %d\nMy father is %d\n", getpid(), getppid());pause(); //暂停,等待键盘中断信号唤醒 //子进程1被键盘中断信号唤醒继续执行 printf("%d child1 will Running: \n", getpid()); // //装入并执行新的程序 status1 = execve(args1[0], args1, NULL);}else //父进程执行代码段 {printf("\nI am Parent process %d\n", getpid()); //报告父进程进程号 pid2 = fork();if(pid2<0){printf("Create Process2 fail!\n");exit(EXIT_FAILURE);}if (pid2 == 0) // 子进程执行代码段 {//报告父子进程进程号 printf("I am Child2 process %d\nMy father is %d\n", getpid(), getppid());//装入并执行新的程序 status2 = execve(args2[0], args2, NULL);//子进程2执行完了,唤醒子进程1/* 系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。 *///所以,下面的部分并没有执行,所以需要手动按Ctrl+C唤醒,而不是自动发信号唤醒 /*if (kill(pid1, SIGINT) == 0)printf("%d Wakeup  its brother %d.\n", getpid(), pid1);else printf("%d send signal failed.\n", getpid());*/}}waitpid(pid2, &status2, 0); //等待子进程结束printf("\nMy child2 exit! status = %d\n\n", status2);if (kill(pid1, SIGINT) == 0)printf("%d Wakeup   %d.\n", getpid(), pid1);else printf("%d send signal failed.\n", getpid());waitpid(pid1, &status1, 0); //等待子进程结束printf("\nMy child1 exit! status = %d\n\n", status1);return EXIT_SUCCESS;}

exec函数介绍(整理)(附带:操作系统实验一:进程控制实验 代码)相关推荐

  1. 操作系统实验:Linux下的进程控制实验

    进程控制实验 一.实验目的: 二.实验平台: 三.实验内容: 1.进程的创建与销毁 进程控制相关函数 实验结果分析 2.多进程并发执行 time命令 实验结果分析 四.总结分析 一.实验目的: 加深对 ...

  2. 实验2linux进程控制与通信,实验2 进程控制与通信管理word文档良心出品

    <实验2 进程控制与通信管理word文档良心出品>由会员分享,可在线阅读,更多相关<实验2 进程控制与通信管理word文档良心出品(13页珍藏版)>请在人人文库网上搜索. 1. ...

  3. linux 实验2 进程创建,实验2Linux进程控制与通信

    实验2Linux进程控制与通信 实验 2 Linux 进程控制与通信1. 实验目的(1 ) 进一步认识并发执行的概念,认识父子进程及进程创建原理:(2 ) 了解 Linux 系统中进程通信的基本原理. ...

  4. linux系统进程控制实验报告,Linux进程控制实验报告.doc

    里奴性进程控制实验报告 实验名称: Linux进程控制 实验要求:一.编写一个Linux系统C程序,由父亲创建2个子进程,再由子进程各自从控制台接收一串字符串,保存在各自的全局字符串变量中,然后正常结 ...

  5. 计算机实验进程管理与虚拟机,虚拟机VMware进程控制实验.docx

    虚拟机VMware进程控制实验 实验6:进程控制操作 1.实验目的 1.了解进程的概念: 2.熟悉Linux的前台与后台进程控制操作: 3.掌握利用进程监控工具来维护系统的正常运行: 2.实验内容 1 ...

  6. 操作系统—进程控制实验

    文章目录 1.关于实验前环境准备 2.关于可能用到的命令 3.关于makefile 4.关于实验说明 5.关于实验指导的程序 6.关于独立实验 Q(跪求大佬解答)? 1.关于实验前环境准备 要准备好C ...

  7. 实验四 linux进程控制实验报告,Linux系统进程控制操作系统实验报告4

    实验课程名称:操作系统 实验项目名称Linux系统进程控制实验成绩 实验者专业班级组别 同组者实验日期年月日第一部分:实验分析与设计(可加页) 实验内容描述(问题域描述) 要求:掌握Linux系统中进 ...

  8. 操作系统 | 实验一 进程控制

    文章目录 一.实验目的 二.实验内容 三.实验步骤 3.1 数据结构 3.2 程序流程图 四.实验代码 五.实验结果 六.实验体会总结 一.实验目的 1.理解进程的概念,明确进程和程序的区别 2.理解 ...

  9. c语言进程控制实验报告,操作系统进程的创建与控制实验报告.doc

    操作系统实验报告 实验一 进程的创建和控制 班 级: 12计算机12班 学 号: 127401219 姓 名: 刘艳仙 成 绩: 2013年 实验目的 1.掌握进程的概念,明确进程的含义 2.复习C语 ...

最新文章

  1. 哪个版本好_《道德经》道尽人生大智慧,哪个版本《道德经》的注释比较好呢?...
  2. Android之横向滑动的广告(网格控件)
  3. 深圳网络推广提醒大家做好URL标准化,网站排名“事半功倍”!
  4. 技术规划应该写成什么样?
  5. ci mysql 缓存_CodeIgniter框架中启用和清除缓存的教程
  6. Visual studio C++ MFC之列表控件CListCtrl Control
  7. 客户端工具收取邮件提示-ERR maildrop alredy locked
  8. sql server中扩展存储过程随笔
  9. python HtmlTestRunner python2.x python3.x报告优化模板源码下载
  10. CAN FD 总线协议深度解析-简单易懂协议详解
  11. antdvue 表格插入自定义行
  12. VScode设置目录分级显示
  13. 90后小伙自己开发APP年赚10亿,自己开发APP需要什么工具
  14. Wavefront OBJ 转换成OpenGL ES使用的C/C++文件
  15. 认识网络号与子网划分
  16. Ansys在高分屏电脑下的显示以及Fluent的图形显示界面黑屏问题
  17. 汤松榕:人工智能赋能多应用场景 助力企业实现数字化转型
  18. 2023每日发布行业及概念热点切换跟踪图!
  19. python 抽奖器_python编写实现抽奖器
  20. 课得软件丨纵观全球程序员税后年收入,中国排在第几?

热门文章

  1. 算法学习:强连通分量 --tarjan
  2. 【codeforces 807C】Success Rate
  3. 前端画面-下拉后滚动
  4. 拼接图像亮度均匀调整_液晶拼接屏如何才能达到更好的显示效果
  5. Docker Machine-Windows
  6. 设计模式复习-解释器模式
  7. 《NO STRATEGY》《重塑战略》
  8. C语言经典例32-删除字符串中指定的字符
  9. 【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 五 )
  10. 【Android 组件化】路由组件 ( 注解处理器获取被注解的节点 )