子进程与父进程运行不同程序

news2024/9/19 10:44:33

往文件里面写内容,fork在open之前,会接着父进程写的内容写,继承父进程的状态信息,文件描述符一直往下

往文件里面写内容,fork在open之后,分别打开文件,后运行的会覆盖先运行的内容

让低8位有效

进程的终止:8种情况
    1)main 中 return
    2)exit() //库函数 
       c库函数,会执行io库的清理工作,关闭所有 的流,以及所有打开的文件。
       注册清理函数(atexit)。
    3)_exit,_Exit 会关闭所有的已经打开的文件,不执行清理函数。 //系统调用 
    
    //4) 主线程退出  
    //5)主线程调用pthread_exit 
    
    异常终止:
    6)abort()
    7)signal   kill pid
    //8) 最后一个线程被pthread_cancle

僵尸进程:
    进程执行结束但空间未被回收变成僵尸进程

    1.exit     库函数
    退出状态,终止的进程会通知父进程,自己使如何终止的。    
    如果是正常结束(终止),则由exit传入的参数。
    如果是异常终止,则有内核通知异常终止原因的状态。
    任何情况下,父进程都能使用wait,waitpid获得这个状态,以及资源的回收。
    
    
    void exit(int status) 
    exit(1);
    功能:
        让进程退出,并刷新缓存区
    参数:
        status:进程退出的状态
    返回值:
        缺省
    
    EXIT_SUCCESS    0
    EXIT_FAILURE    1

    return  当该关键字出现在main函数中时候可以结束进程
            如果在其他函数中则表示结束该函数。
    
    
    exit -> 刷新缓存区 -> atexit注册的退出函数 -> _exit
    
    2._exit    系统调用
    void _exit(int status);
    功能:
        让进程退出,不刷新缓存区
    参数:
        status:进程退出状态
    返回值:
        缺省

    
             mian(int agc,argv)
{
    main();
}             
    
    回调函数
    3.atexit
    int atexit(void (*function)(void));
    功能:
        注册进程退出前执行的函数
    参数:
        function:函数指针
            指向void返回值void参数的函数指针
    返回值:
        成功返回0
        失败返回非0

    当程序调用exit或者由main函数执行return时,所有用atexit
    注册的退出函数,将会由注册时顺序倒序被调用

注意:
   a. 是exit函数调用时,会调atexit函数 
      _exit函数调用时,不会调到atexit
   b. atexit 程序正常结束
      (1).main 返回 //exit 
      (2).exit()        
   c.atexit函数 可以多次注册 
   d.最后"退出清理函数"的调用顺序,与注册顺序相反。
    

3.进程空间的回收
    
    exit(20);----
    void exit(int status);

/系统镜像 
img == 镜像 

exec


       int exec l(const char *path, const char *arg, ...);
       int exec l p(const char *file, const char *arg, ...);
       int exec l e(const char *path, const char *arg,..., char * const envp[]);
       int exec v(const char *path, char *const argv[]);
       int exec v p(const char *file, char *const argv[]);
       int exec v pe(const char *file, char *const argv[], char *const envp[]);


int exec l(const char *path, const char *arg, ...);
int exec v(const char *path, char *const argv[]);

l --- list

//ls -l / 

path  ---文件路径 
"/bin/ls"
arg  ---> 要执行的 文件的名字 
"ls"

"-l"
"/"
NULL 表示结束 

v --- vector (向量) victor

p --- path //PATH (可执行文件路径)

execute
exec族(环境变量用NULL作为终止符才能在子程序中运行
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),
子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的
用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建
新进程,所以调用exec前后该进程的id并未改变。
其实有六种以exec开头的函数,统称exec函数:
vector
ls -l -i list 
execl("/bin/ls","-l","-i",NULL);
execlp("ls","-l","-i",NULL);

#include <unistd.h>
int execl(const char *path, const char *arg, ...);
int execv(const char *path, char *const argv[]);

key=value
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execle(const char *path, const char *arg, ..., char *const envp[]);

int execve(const char*path,char*const argv[],char*const evnp[]);
int execlp(const char *file, const char *arg, ...);
echo $PATH
PATH= 
int execvp(const char *file, char *const argv[]);


int execve(const char *path, char *const argv[], char *const envp[]);

这些函数的区别
    1),前4个使用路径名作为参数,后面两个使用文件名做参数
    当filename中,含有/时视为路径名,否则就按PATH变量,在指定目录下查找可执行文件。
    2)相关的参数表传递
    l表示list,v表示vector
    execl,execlp,execle,需要将参数一个一个列出,并以NULL结尾。
    execv,execvp,execve,需要构造一个参数指针数组,然后将数组的地址传入。

    3)以e结尾的函数,可以传入一个指向环境字符串的指针数组的指针。其他未指定环境变量,使用父进程继承过来的。
execve 是真正的系统调用
这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回,如果调用出错
则返回-1,所以exec函数只有出错的返回值而没有成功的返回值。

char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};
char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL};
execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execv("/bin/ps", ps_argv);
execle("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL, ps_envp);
execve("/bin/ps", ps_argv, ps_envp);

在 C 语言中,当你使用 exec* 系列函数(如 execve, execl, execle, execvp, execvpe 等)来执行一个新的程序时,环境变量通常需要以 NULL 指针作为数组的终止符。这是因为 exec* 函数期望环境变量以一个字符串数组的形式传递,并且这个数组的最后一个元素必须是 NULL 指针。为什么需要 NULL 终止符1. 数组的边界:•在 C 语言中,数组的边界通常通过 NULL 指针来确定。NULL 指针作为数组的最后一个元素,告诉函数处理到此处为止。2. 环境变量的格式:•环境变量通常是以字符串数组的形式传递给程序的。每个环境变量本身是一个字符串,例如 "VAR=value"。为了指示环境变量数组的结束,需要一个 NULL 指针。
execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);
execvp("ps", ps_argv);

-----------------------------
注意:
路径加文件名
1.excle 
  带l的默认会搜索,当前路径下。
2.带p的只搜索 
  只搜索PATH系统环境变量
-----------------------------


       int exec l  (const char *path, const char *arg, ...);
       int exec l p (const char *file, const char *arg, ...);
       int exec l e (const char *path, const char *arg,..., char * const envp[]);
       int exec v  (const char *path, char *const argv[]);
       int exec v p (const char *file, char *const argv[]);
       int exec v p e(const char *file, char *const argv[],char *const envp[]);


(1).带l  vs 带 v 

      
    int execl  (const char *path, const char *arg, ...); //list 
    int execv  (const char *path, char *const argv[]);//vector --- 


功能:
    执行一个文件 (可执行文件 a.out / 1.sh )
     image 映像/镜像
 
 text|data|bss|堆 栈|环境变量及命令行参数 + pcb
 
   用新进程的 镜像 替换 调用进程的 镜像 
参数:
  @path   要执行的文件的路径(包含可执行文件的名字)
   
  eg:
      ls       
      /bin/ls 
      
  @arg   表示 可执行文件的文件名 

     ls  
    
  ... 可变参数 
 
 
 ls -l / 
 
 最后写一个NULL 表示结束 
 
 ls -l /
 
 execl("/bin/ls","ls","-l","/",NULL);

区别:
    在于,参数传递的方式不同,
    l --- list ---参数逐个列举 
    eg:
     execl("/bin/ls","ls","-l","/",NULL);
    v ---vector --- 参数组织成 指针数组的形式 
    eg:
      char *const arg[] = {"ls","-l","/",NULL};
      execv("/bin/ls",arg);
      

2). p vs e
int execl   (const char *path, const char *arg, ...); //list 
int execv   (const char *path, char *const argv[]);//vector --- 
int execl p (const char *file, const char *arg, ...);
int execv p (const char *file, char *const argv[]);

int execl  e (const char *path, const char *arg,...,   char * const envp[]);
int execvp e(const char *file, char *const argv[]  ,   char * const envp[]);
p --- path ->PATH (环境变量 --- 都是可执行文件的路径)

带p 表示可执行文件的寻找方式,是从系统的环境变量PATH中的路径下面去找
带e 表示的是可以给要执行的 新程序 传递需要的 环境变量 

extern char **environ; //系统的环境变量信息 的指针数组的首地址 

int execle (const char *path, const char *arg,...,   char * const envp[]);
int execvpe(const char *file, char *const argv[]  ,   char * const envp[]);


            [                    ] //字符串的的 首地址 
            ["HOME"="/linux/home"]
            ["shell"="/bin/bash" ]
            ...
            

真正的系统调用:
execve  
      

进程执行:
//1.父进程干相同的事情 
   fork 
   
   eg:
   12306 
//2.创建的子进程 
    进行新程序的执行 
    fork + exec 

    bash 
     |
    vfork
    / \
bash(f) bash+exec(a.out)   //virtual (虚拟) 


 eg:
    shell 
    

思考:
    
   效率? --- 高 
   
   提高效率? 

|系统信息|  
----------
|栈      |
|堆      |
----------
| bss    |
----------
|data    |
----------  
| text   |  <----->
---------- 
      
copy-on-write (当写(修改)的时候 拷贝) //写时拷贝

尽可能提高进程创建的效率。




 


 


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2035290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LVS-NAT + LVS-DR

LVS 现在lvs已经是linux内核标准的一部分&#xff0c;使用lvs可以达到的技术目标是&#xff1a;通过linux达到负载均衡技术和linux操作系统实现一个高性能高可用的linux服务器集群&#xff0c;他具有良好的可靠性&#xff0c;可延展性和可操作性&#xff0c;从而以低廉的成本实…

AQS的同步队列和条件队列原理

文章目录 二者区别实现原理同步队列原码-内部类Node源码-获取锁源码-释放锁条件队列原码-内部类Node源码-等待源码-唤醒Demo-比较典型的条件队列使用场景二者区别 首先,AQS中的 同步队列 和 条件队列 是两种不同队列: 目的不同:同步队列主要用于实现锁机制(也就是锁的获取…

4.3.2 C++ 平面拟合的实现

4.3.2 C 平面拟合的实现 参考教程&#xff1a; gaoxiang12/slam_in_autonomous_driving: 《自动驾驶中的SLAM技术》对应开源代码 (github.com) Eigen打印输出_打印eigen矩阵-CSDN博客 1. 编写 Plane fitting 1.1 创建文件夹 通过终端创建一个名为Plane_fitting的文件夹以保…

Cookie和Session的区别(详细讲解)

Session 和 Cookie 的区别 在网络通信过程中&#xff0c;使用的是HTTP协议&#xff0c;它是一种无状态协议&#xff0c;比如&#xff0c;在登录一个网站时&#xff0c;登录成功后&#xff0c;之后在访问这个网站的其他页面时&#xff0c;都需要重新登录&#xff0c;无法识别出…

[240812] X-CMD 发布 v0.4.5:更新 gtb、cd、chat、hashdir 模块功能

目录 &#x1f4c3;Changelog✨ gtb✨ cd✨ chat✨ hashdir &#x1f4c3;Changelog ✨ gtb 调整了 fzf 预览窗口中书籍文本的显示效果&#xff0c;通过识别文本中的特殊字符、日期、章节标题等信息&#xff0c;为其赋予不同的颜色。 ✨ cd cd 模块新增功能&#xff1a;在找…

网络编程day03 20240813

一、相关练习 1、通过w(红色臂角度增大)s&#xff08;红色臂角度减小&#xff09;d&#xff08;蓝色臂角度增大&#xff09;a&#xff08;蓝色臂角度减小&#xff09;按键控制机械臂 机械臂需要发送16进制数&#xff0c;共5个字节&#xff0c;协议如下&#xff1a; 0xff 0x0…

数据库核心技术:存储与索引概览

文章目录 存储与索引技术概览存储结构索引技术 MySQL存储结构索引技术事务与锁优势 PostgreSQL存储结构索引技术事务与锁优势 Oracle存储结构索引技术事务与锁优势 SQL Server存储结构索引技术事务与锁优势 选型考量存储结构索引技术事务与锁的支持综合因素未来趋势 结语 数据库…

【微信小程序】网络数据请求

1. 小程序中网络数据请求的限制 2. 配置 request 合法域名 3. 发起 GET 请求 调用微信小程序提供的 wx.request() 方法,可以发起 GET 数据请求,示例代码如下: 4. 发起 POST 请求 调用微信小程序提供的 wx.request() 方法,可以发起 POST 数据请求,示例代码如下: 5. …

今日头条的账号id在哪里看(网页版)

今日头条的账号id在哪里看&#xff08;网页版&#xff09; 1.https://mp.toutiao.com/profile_v4/index2.登录今日头条账号3.设置->头条号ID 1.https://mp.toutiao.com/profile_v4/index 2.登录今日头条账号 3.设置->头条号ID 打开下方链接&#xff1a; https://mp.to…

进程的执行与结束

一、文件的读写 1、fork之前open 子进程会继承父进程已打开的文件相关信息 所以&#xff0c;此时父子进程会影响一个offset值 2、fork之后open 父子进程各自有各自的打开文件的信息&#xff0c;相互之间不会有影响。 二、 进程的执行 //进程运行时&#xff0c;典型场景 1…

量化策略开发步骤系列(3)关键投资组合指标

量化策略开发步骤系列&#xff08;3&#xff09;关键投资组合指标 投资组合指标波动性夏普比率最大回撤赢/输百分比每笔交易的平均利润/亏损每期交易次数风险价值&#xff08;VaR&#xff09; 这是量化交易系列文章的第二系列——量化策略开发步骤&#xff0c;第一系列请参考专…

Prometheus+Grafana-3-Nginx监控-Redis监控

一、监控Nginx 1.Nginx需要开启stub_status 这里我的nginx容器名为mynignx&#xff0c;进入容器查看。 docker exec -it mynginx bash #进入容器 nginx -v 2>&1 | grep -o with-http_stub_status_module #查看 修改nginx.conf ...location /stub_status {stub_stat…

华为od统一考试B卷【AI面板识别】python实现

思路 n int(input())class Light:def __init__(self, id, x1, y1, x2, y2):self.id idself.x1 x1self.y1 y1self.x2 x2self.y2 y2self.height y2 - y1def get_lights_info(n):lights []for _ in range(n):id, x1, y1, x2, y2 map(int, input().strip().split())lights…

量产工具——复习及改进(后附百问网课程视频链接)

目录 一、函数的使用 1.显示系统 1.1 mmap函数 2.输入系统 2.1 ts_setup()函数 2.2 ts_read()函数 2.3 socket()函数 2.4 bind()函数 2.5 recvfrom()函数 2.6 inet_aton()函数 2.7 sendto()函数 2.8 pthread_create()函数 2.9 pthread_cond_signal()函数 2.10 pthre…

思科路由器的基本配置1

#路由技术基础# #路由器的基本配置1# #1调整超级终端的参数 #2退出配置向导&#xff0c;输入“NO”即可进入正常配置方式 #3路由器的模式切换 Router> &#xff01;进入用户模式 Router>enable &#xff01;进入特权模…

opencv-python实战项目一:获取鼠标框选区域的颜色

文章目录 一&#xff1a;简介二&#xff1a;框选区域选择颜色方案三、算法实现步骤3.1 按鼠标事件截取图像3.2将图像模糊后转化为hsv并求均值3.3 判断hsv处于何种颜色 四&#xff1a;整体代码实现五&#xff0c;效果: 一&#xff1a;简介 在计算机视觉领域&#xff0c;颜色检测…

19-ESP32-C3加大固件储存区

1默认编译情况。 2、改flash4M。ESP-IDF Partition Table Editor修改。 3、设置输入Partition Table 改自定义.CSV。保存。 4、查看命令输入Partition Table Editor打开-分区表编辑器UI。按图片增加。 nvs,data,nvs,0x9000,0x6000,, phy_init,data,phy,0xF000,0x1000,, factory…

计算机毕业设计Hadoop+Hive居民用电量分析 居民用电量可视化 电量爬虫 机器学习 深度学习 大数据毕业设计 Spark

《Hadoop居民用电量分析》开题报告 一、研究背景与意义 能源问题在全球范围内一直是热点议题&#xff0c;尤其是随着居民生活水平的提高和城市化进程的加快&#xff0c;居民用电量急剧增长&#xff0c;对电力系统的稳定运行和能源管理提出了更高要求。如何科学合理地管理和分…

Hive3:识别内部表、外部表及相互转换

一、识别方法 查看内部表信息 desc formatted stu;查看外部表信息 desc formatted test_ext1;通过Table Type对应的值&#xff0c;我们可以区分外部表和内部表。 二、相互转换 内部表转外部表 alter table stu set tblproperties(EXTERNALTRUE);外部表转内部表 alter ta…

PCIe学习笔记(21)

读请求的数据返回&#xff08;Data Return for Read Requests&#xff09; •针对内存读取请求的单个完成可能提供少于请求的全部数据量&#xff0c;只要对于给定请求的所有完成在组合起来时返回了读取请求中请求的数据量。 ◦不同请求的完成不能合并。 ◦I/O和Configuratio…