首页 > 系统相关 >[Linux]fork与exec

[Linux]fork与exec

时间:2023-02-01 15:22:06浏览次数:45  
标签:fork status exec pid echo Linux include

写这篇文章的原因是看到了一段与 Linux 下进程复制有关的代码,感觉很神奇,不甚理解,所以找了一些相关的资料想要弄明白 Linux 的 fork、进程复制到底是怎么工作的,于是有了这篇文章。
那段代码是这样的:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <wait.h>
int main() {
	int pid, status;
	pid = fork();
	if (pid == 0) {
		// /bin/echo是 Linux 自带的 echo 命令的源代码所在的位置
		char *argv[] = {"/bin/echo是 Linux 自带的 echo 命令的源代码所在的位置", "THIS","MESSAGE", "IS", "FROM", "ECHO", NULL};
		execve("/bin/echo", argv, NULL);
		printf("exec failed!\n");
		exit(1);
	} else {
		printf("parent wating!\n");
		wait(&status);
		printf("the child exited with status %d \n", status);
	}
	exit(0);
}
(base) root@iZuf65cax8rsfekcyp3ytyZ:~/testfork# gcc tfork.c -o test
(base) root@iZuf65cax8rsfekcyp3ytyZ:~/testfork# ./test
parent wating!
THIS MESSAGE IS FROM ECHO
the child exited with status 0 

如果上面的代码是调用了系统的 echo 命令,如果我们把命令换成一个不存在的命令,那么就会报错,我们来修改一下代码生成 errorfork.c :

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <wait.h>
int main() {
	int pid, status;
	pid = fork();
	if (pid == 0) {
		// 当前目录下没有名为 echo 的文件,所以 execve 会执行失败
		char *argv[] = {"echo", "THIS","MESSAGE", "IS", "FROM", "ECHO", NULL};
		execve("echo", argv, NULL);
		printf("exec failed!\n");
		exit(1);
	} else {
		printf("parent wating!\n");
		wait(&status);
		printf("the child exited with status %d \n", status);
	}
	exit(0);
}
(base) root@iZuf65cax8rsfekcyp3ytyZ:~/testfork# gcc errorfork.c -o errorfork
(base) root@iZuf65cax8rsfekcyp3ytyZ:~/testfork# ./errorfork
parent wating!
exec failed!
the child exited with status 256 

大家可以用在线C语言编译器 来做一下这个实验试试看。
我当时看到这个实验觉得有两点很不能理解:

  • fork() 函数调用返回了两个值,if 和 else 子句都会被执行,超出认知了,感觉很神奇。
  • 如果 execve 函数执行成功了,这个函数后面的代码就不会再被执行了,只有失败了就会继续执行下去,超出认知了,为什么一个函数调用,如果成功了它就不会回到它的原始调用点了?

基于这两个疑惑我找了一些资料,了解了 fork 的运行机制,总结成了这篇文章。

初识 fork

fork 是叉子的意思,进程复制函数为什么要交 fork 呢,这就要从 fork 的起源说起了
image
fork 的思想最初是 Conway 作为一种 多处理器并行的方案提出来的,这个想法非常有意思。简而言之,fork 思想来源于流程图。看上面这张流程图,从 fork 点开始产生分叉,产生了一个新进程,可以和原来的进程并行执行,就像叉子一样。
先来解决第一个疑惑,为什么 fork 函数会有两个返回值, if 和 else 语句都会被执行到?因为 fork 函数是把父进程完全复制了一遍,所以复制出来的子进程它下一步应该执行的就是 if 语句, 父进程要执行的代码一样,只是他俩的 pid 不一样,所以进入了不同的选择分支
再来解决第二个疑惑,为什么执行 exec 函数成功之后就不回到原来的函数调用点了?因为 exec 把所要执行的新的函数代码加载到了这个子进程里,子进程原始的代码就无了,自然也不会回到调用 exec 的地方了。

标签:fork,status,exec,pid,echo,Linux,include
From: https://www.cnblogs.com/kirizi/p/17037332.html

相关文章

  • Linux使用gtest测试so文件
    我使用的环境是Ubuntu22.04.1LTSgoogletest的下载链接:https://github.com/google/googletest/archive/refs/tags/v1.13.0.zip下载下来之后解压,cd到解压的文件夹里面......
  • Linux+libusb开发用户USB无驱通讯
    0.libusb的介绍:参考[1]1.环境:vmware_fedora_10(linux-2.6.x)2.获取源代码:http://sourceforge.net/projects/libusb/(最好选择libusb-1.0.9版本,下载次数最多,自是有它的......
  • Linux 安装 CentOS7
    1、linux下载http://mirrors.aliyun.com/centos/7/isos/x86_64/centos-7-isos-x86_64安装包下载_开源镜像站-阿里云(aliyun.com)选择绝大多数人下载的版本就可以了,使......
  • Linux逻辑卷
    Linux逻辑卷架构与相关命令1.为什么要设计逻辑卷(lvm)Linux操作系统中的存储/文件系统,一般都是基于磁盘分区策略来实现的。这过程类似聚会上切蛋糕,一块蛋糕切出来,再分给......
  • linux
    linuxubantu中放大终端窗口的字体显示ctrl+shift+=缩小ctrl+-自动补全tab曾经使用的命令向上键另起一行ctrl+c常见命令命令作用ls查看当前文件......
  • Linux设置动态链接库so的默认搜索路径
    众所周知,Linux动态库的默认搜索路径是/lib和/usr/lib,64位系统是/lib64和/usr/lib64。动态库被创建后,一般都复制到这两个目录中。当程序执行时需要某动态库,并且该动态库......
  • Linux Nginx安装以及可能出现错误
    一、编译安装makemakeinstallmake的过程是把各种语言写的源码文件,变成可执行文件和各种库文件;makeinstall是把这些编译出来的可执行文件和库文件复制到合适的地方。......
  • linux服务器运行java项目, 监控查看内存、储存空间和cpu占用率
    服务器部署方式为tomcat中运行war包的方式,有一次重新部署时候发现报异常堆栈溢出了.想要定位到某个war包中通过学习整理出此篇文章以作记录笔记.1.关于内存过高......
  • Linux创建新用户并配置远程连接
    useraddz #创建用户ztail-f/var/log/audit/audit.log#查看登录日志sudovi/etc/sudoers#查看权限,并修改权限  #增加sudo到root权限“#inc......
  • Linux创建文件报错:/bin/bash^M: bad interpreter
    在使用Linux创建好文件shell文件之后,发生了这样一个错误:/bin/bash^M:badinterpreter查找资料后发现:在执行shell脚本时提示这样的错误主要是由于shell脚本文件是dos格式,即......