linux高级系统编程之进程

进程

一个正在进行的程序

并行与并发

并行:执行的程序在不同CPU上同时执行

并发:一个CPU,多个进程交替执行,因为交替速度很快,所以从宏观上来看是同时执行的,但是从围观的角度是交替执行的

单道与多道

单道程序设计:所有进程一个一个排队执行,若A阻塞,B只能等待,,即使CPU处于空闲状态

多道程序设计:在计算机内存中同时存放几道相互独立的程序,它们在管理程序控制之下,相互穿插的运行

进程控制块(PCB)

进程运行时,内核为每个进程分配一个PCB(进程控制块),维护进程相关的信息,linux内核的进程控制块是task_struct结构体

task_struct结构体

/usr/src/linux-headers-xxx/include/linux/sched.h 文件中可以查看
task_struct 结构体定义

其内部成员有很多
如:
        进程id:语言使用pid_t的类型表示,其实就是一个非负整数
        进程的状态:有就绪,运行,挂起,停止等状态
PCB存储位置
在内核中
                

进程号

当前进程的id就是进程号,由系统分配

每个进程都由一个进程号来标识,其类型为pid_t,进程号的范围:0~32767

进程号总是唯一的,但进程号可以重用,当一个进程终止后,其进程号就可以再次使用了

进程号为0和1的进程由内核创建

进程号为0的进程通常是调度进程,常被称为交换进程,进程号为1的进程通常是init进程

除调度进程(0号进程)外,在linux下面所有的进程都是由init(1号进程)进程直接或间接创建的

进程号(PID)

        标识进程一个非负整型数

        对应函数:

                pid_t getpid()        获取当前进程的进程号

进程组号(PGID)

        多个进程在同一个组中,该组就是进程组

        该组中第一个进程为组长进程,该组长进程的进程id就是该进程组id

        由进程A开启的子进程默认进程A为同组进程,此时A就是组长进程

        对应函数;

                pid_t getpgid(int pid)         获取指定进程所在的进程组号

父进程号(PPID)

        由进程A开启进程B,此时进程A就是进程B的父进程,进程B就是进程A的子进程

        对应函数:

                pid_t getppid()        获取当前进程的父进程号

                当进程A比进程B先销毁时,此时进程B就是孤儿进程,由1进程充当其父进程        

 扩展

命令:ps

作用:查看进程状态

参数:

        -a 显示终端上的所有进程,包括其他用户的进程

        -u 显示进程的详细状态

        -x 显示没有控制终端的进程

        -w 显示加宽,以便显示更多的信息

        -r 只显示正在运行的进程

        

        ps -aux:显示当前用户在运行到的进程信息

        ps -ajx:显示正在运行的相关联进程信息(包含父进程id(ppid),组id(pdid))

显示信息中STAT参数含义

        D 不可中断 Uninterruptibleusually IO

        R 正在运行,或在队列中的进程
        S(大写 ) 处于休眠状态
        T 停止或被追踪
        Z 僵尸进程
        W 进入内存交换(从内核 2.6 开始无效)
        X 死掉的进程
        < 高优先级
        N 低优先级
        s 包含子进程
        l 表示线程加锁
        + 位于前台的进程组

fork函数

作用:创建进程

语法:

        pid_t fork();

返回值:

        如果在子进程中就是0,如果在父进程中就是创建的子进程id,-1创建失败

        fork失败的两个主要原因是;

                1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN

                2)系统内存不足,这时errno的值被设置为ENOM

注意:

        1,子进程会从fork函数后开始执行

        2,子进程共享父进程所有内容,不包括进程号,父进程号等

                使用fork函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间

                 地址空间:包括进程上下文,进程堆栈,打开的文件描述符,信号控制设定,进程优先级,进程组号等

                子进程所独有的只有它的进程号,计时器等

                此外,使用fork函数的代价是很大的

        3,谁创建谁回收

进程状态

三状态:就绪态  执行态 等待态

五状态:新建态 终止态 运行态 就绪态 阻塞态

注意:

        阻塞态在其他语言中进行细分又可以分为阻塞态与休眠态

        休眠态又可以分为有限期休眠与无限期休眠

        休眠状态下不会抢夺CPU执行权

进程资源的回收

每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存资源等,但是任然为其保留一定的信息,这些信息主要指的是进程控制块的信息(包括进程号,退出状态,运行时间等);

回收原则:谁创建谁回收(父进程回收子进程资源)

wait函数

作用:回收进程资源

头文件:

        #include <sys/types.h>

        #include <sys/wait.h>

语法:

        pid_t wait(int *status);//阻塞

功能:

        等待任意一个子进程结束,如果任意一个子进程结束了,此函数会回收该子进程的资源

参数:

        status:进程退出时的状态信息

返回值:

        成功:已经结束子进程的进程号

        失败:-1

注意:

        1,会阻塞当前进程,知道回收一个子进程

        2,因为谁创建谁回收的原则,所以该函数在父进程中调用

exit函数与_exit函数

作用:退出当前进程

exit函数与_exit函数的区别?

exit函数属于库函数,_exit函数属于系统调用

exit函数所需头文件#include<stdlib.h>,_exit函数所需头文件#include<unistd.h>

exit函数为 void exit(int status) ,_exit函数 void -exit(int status);

两者参数一致:

        退出状态,0,正常退出,非0异常退出

注意:

        退出状态码取值区间:0~255

WIFEXITED(status)与WEXITSTATUS(status)

作用:

        WIFEXITED:获取进程退出时状态

        WEXITSTSTUS:获取进程退出时状态码

语法:

        WIFEXITED(status)

        WEXITSTATUS(status)

waitpid函数

作用:回收进程

头文件:

        #include<sys/types.h>

        #include<sys/wait.h>

语法:

        pid_t waitpid(pid_t pid,int *status,int options);

功能:

        等待子进程终止,如果子进程终止了,此函数会回收子进程的资源

参数:

       pid: 参数 pid 的值有以下几种类型:

                pid>0 等待进程ID等于pid的子进程

                pid=0 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会等待它

                pid=-1等待任一此时waitpid和wait作用一样

                pid<-1 等待指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值

        status:进程退出时的状态信息,和wait()用法一样

        option:option提供了一些额外的选项来控制waitpid()

                0:同wait(),阻塞父进程,等待子进程退出

                WNOHANG:没有任何已经结束的子进程,则立即返回(非阻塞)

                WUNTRACED:如果子进程暂停了则此函数马上返回,并且不予以理会子进程的结束状态

返回值:

        1,当正常返回的时候,waitpid()返回收集到的已经回收子进程的进程号

        2,如果设置了选项WNOHANG,而调用中waitpid()还有子进程在运行,且没有子进程退出,返回0,父进程的所有子进程都已经退出了返回-1,返回>0表示等到一个子进程退出

        3,如果调用中出错,则返回-1,这时error会被设置成相应的值以指示错误所在

atexit函数

作用:进程在退出前可以用atexit函数注册退出处理函数

注意:

        1,一个进程可以登记最多32个函数,这些函数将由exit自动调用,我们称这些函数为终止处理程序,用atexit函数来登记这些函数

        2,以登记这些函数的相反顺序调用他们,同一函数如登记多次,则也会被调用多次

        3,执行注册的函数依据是当前子进程

语法:

        int atexit (void (*__func)(void))

僵尸进程

子进程退出,父进程没有回收子进程资源,子进程为僵尸进程(有害)

子进程的PID被占用,系统的PID是有数量限制

孤儿进程

父进程先结束,子进程为孤儿进程(无害)

孤儿进程被1号进程接管(当孤儿进程结束时,1号进程负责回收其资源)

守护进程

守护进程是在后台独立运行、脱离控制终端且周期性执行任务或等待处理事件的特殊进程,于系统启动时自动开启并持续至系统关闭,它在系统服务支持(如 httpd 提供 Web 服务)、资源管理(如 syslogd 收集日志)、任务调度(如 cron 按计划执行命令)等多方面发挥关键作用,在 Linux 中创建时需先通过 fork () 创建子进程,父进程退出后子进程进一步执行后续设置步骤以成为守护进程并稳定运行

终端

终端:是与计算机系统相连的一种输入输出设备


在UNIX系统中,用户通过终端登录后得到一个shell进程,这个终端成为shell进程的控制终端,进程中,控制终端是保存在PCB中的信息,而fork会复制PCB中的信息,因此由shell进程启动的其他进程的控制终端也是这个终端
 

作用 : 获取当前进程所属终端名称
#include <unistd.h>
char *ttyname(int fd);
功能:由文件描述符查出对应的文件名
参数: fd: 文件描述符
返回值:
成功:终端名
失败: NULL

进程组

代表一个或多个进程的集合

每个进程都有对应的进程组

进程组ID为当前进程中的第一进程ID

如果一个进程ID和组ID相同,那么这个进程就是组长进程

当父进程创建子进程的时候,默认子进程与父进程属于同一进程组

shell进程启动的进程独立为一个进程组

如果进程中只是组长进程结束,当前进程组不会解散,只有进程组的所有进程离开(终止或转移),该进程组才会解散

一个进程可以为自己或子进程设置进程组ID

注意:组长进程不能设置进程组id


如果进程ID==进程组ID==会话ID,那么该进程为会话首进程

获取所属进程组id

所属头文件

        #include<unistd.h>

函数

        pid_t getpgrp(void)

功能:

        获取当前进程的进程组ID

参数:

       无

返回值:

        总是返回调用者的进程组ID

函数:

        pid_t getpgid(pid_t pid);

        功能:获取指定进程的进程组ID

        参数:

                pid:进程号,如果pid=0,那么该函数作用和getpgrp一样

返回值:

        成功:进程组ID

        失败:-1

设置进程组

函数:

        int setpgid(pid_t pid,pid_t pgid)

功能:

        改变进程默认所属的进程组,通常可以用来加入一个现有的进程组或创建一个新进程组

参数:

        将参1对应的进程,加入参2对应的进程组中

返回值:

        成功:0

        失败:-1

会话

会话是一个或多个进程组的集合

一个会话可以有一个控制终端,这通常是终端设备或伪终端设备,建立与控制终端连接的会话首进程被称为控制进程

一个会话中的几个进程组可以一个前台进程组以及一个或多个后台进程组

如果一个会话有一个控制终端,则它有一个前台进程组,其他进程组为后台进程组

如果终端接口检测到断开连接,则将挂断信号发送至控制进程(会话首进程)

函数getsid

作用:获取会话id

所需头文件

        #include<unistd.h>

函数:

        pid_t getsid(pid_t pid);

参数:

        pid: 进程号,pid为0表示查看当前进程 session ID(会话id)

返回值:

        成功:返回调用进程的会话ID

        失败:-1

组长进程不能成为新会话的首进程,新会话首进程必定会成为组长进程

函数setsid

作用:创建会话

所需头文件:

        #include <unistd.h>

函数:

        pid_t setsid(void);

功能:

        创建一个会话,并以自己的ID设置进程组ID,同时也是新会话的ID,调用了setsid函数的进程,既是新的会长,也是新的组长

参数:

        无

返回值:

        成功:返回调用进程的会话ID

        失败:-1

注意:

        1,组长进程不能设置为会话

        2,需要root权限(ubuntu不需要)

        3,新会话丢弃原有的控制终端,该会话没有控制设备

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

git 命令之只提交文件的部分更改

git 命令之只提交文件的部分更改 有时&#xff0c;我们在一个文件中进行了多个更改&#xff0c;但只想提交其中的一部分更改。这时可以使用 使用 git add -p 命令 Git add -p命令允许我们选择并添加文件中的特定更改。它将会显示一个交互式界面&#xff0c;显示出文件中的每个更…

Excel中根据某列内容拆分为工作簿

简介&#xff1a;根据A列的内容进行筛选&#xff0c;将筛选出来的数据生成一个新的工作簿(可以放到指定文件夹下)&#xff0c;且工作簿名为筛选内容。 举例&#xff1a; 将上面的内容使用VBA会在当前test1下生成5个工作簿&#xff0c;工作簿名分别为TEST1.xls TEST2.xls TEST3…

数据结构 (10)队列

前言 队列是一种特殊的数据结构&#xff0c;它遵循先进先出&#xff08;FIFO&#xff0c;First In First Out&#xff09;的原则。 一、定义与基本概念 定义&#xff1a;队列是一种只允许在一端&#xff08;队尾&#xff09;进行插入操作&#xff0c;而在另一端&#xff08;队头…

Tomcat10部署Servlet加载错误问题解决

Servlet加载错误&#xff1a;HelloServlet不是Servlet 环境信息&#xff1a;IDEA中的maven项目&#xff0c;tomcat10.1.33 问题信息&#xff1a;XXX.Servlet不是Servlet 问题原因&#xff1a;tomcat10将JavaEE也换成了Jakarta EE&#xff1b; Jakarta EE较以前的JavaEE有一个重…

2024年第十三届”认证杯“数学中国数学建模国际赛(小美赛)

↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓

百度智能云发布首个空间智能解决方案,百度AI优势如何分析?

首先&#xff0c;百度智能云此次推出的空间智能解决方案&#xff0c;在技术底座上展现了其强大的AI异构计算能力。百度百舸AI异构计算平台作为该方案的底层支撑&#xff0c;为2D和3D应用中的人物、物件及场景生成提供了强大的算力支持。这一平台的推出&#xff0c;不仅提升了空…

RTSP摄像头、播放器为什么需要支持H.265?

H.264还是H.265&#xff1f; 好多开发者在做选RTSP播放器的时候&#xff0c;经常问我们的问题是&#xff0c;用H.264好还是H.265好&#xff1f;本文我们就H.264 和 H.265的主要区别和适用场景&#xff0c;做个大概的交流。 一、压缩效率 H.265 更高的压缩比 H.265 在相同视频…

BGP协议路由黑洞

一、实验环境 1、分公司与运营商AS自治系统内运行IGP路由协议OSPF、RIP或静态路由&#xff0c;AS自治系统内通过IBGP路由协议建立BGP邻居关系。 2、公司AS自治系统与运营商AS自治系统间运行EBGP路由协议。 3、通过loopback建立IBGP与EBGP邻居关系&#xff0c;发挥loopback建立…

解决数据传送问题:内网http传输

在服务器上启http服务 在服务器上输入命令&#xff1a; python3 -m http.server 1234 回车启动 访问和下载方法&#xff1a; 然后可以在本地的浏览器上访问&#xff1a;服务器IP:1234 例如192.11.1.1:1234&#xff0c;然后就可以下载对应文件夹下的东西了 在本地上启htt…

飞塔防火墙只允许国内IP访问

飞塔防火墙只允许国内IP访问 方法1 新增地址对象&#xff0c;注意里面已经细分为中国内地、中国香港、中国澳门和中国台湾 方法2 手动新增国内IP的对象组&#xff0c;目前好像一共有8632个&#xff0c;每个对象最多支持600个IP段

《Learn Three.js》学习(3)光源

前言&#xff1a; WebGL本身不支持光源&#xff0c;不使用three.js,则需使用着色程序来模拟光源。 学习大纲&#xff1a; Three.js中的光源 特定光源的使用时机 如何调整和配置所有光源的行为 如何创建镜头光晕 光源表 基础光源&#xff1a;THRER.AmbientLight、THERE.Point…

Linux——基础命令(2) 文件内容操作

目录 ​编辑 文件内容操作 1.Vim &#xff08;1&#xff09;移动光标 &#xff08;2&#xff09;复制 &#xff08;3&#xff09;剪切 &#xff08;4&#xff09;删除 &#xff08;5&#xff09;粘贴 &#xff08;6&#xff09;替换,撤销,查找 &#xff08;7&#xff…

鸿蒙开发App 如何通过抓包查看 http 网络请求?

通过借助第三方工具 Charles https://www.charlesproxy.com/ https://www.zzzmode.com/mytools/charles/https://www.zzzmode.com/mytools/charles/ Charles 激活码计算器 相关博客日志&#xff1a;https://zhuanlan.zhihu.com/p/281126584 MAC上的使用方法&#xff1a; ch…

【Git】Git 完全指南:从入门到精通

Git 完全指南&#xff1a;从入门到精通 Git 是现代软件开发中最重要的版本控制工具之一&#xff0c;它帮助开发者高效地管理项目&#xff0c;支持分布式协作和版本控制。无论是个人项目还是团队开发&#xff0c;Git 都能提供强大的功能来跟踪、管理代码变更&#xff0c;并保障…

分布式锁的实现原理

作者&#xff1a;来自 vivo 互联网服务器团队- Xu Yaoming 介绍分布式锁的实现原理。 一、分布式锁概述 分布式锁&#xff0c;顾名思义&#xff0c;就是在分布式环境下使用的锁。众所周知&#xff0c;在并发编程中&#xff0c;我们经常需要借助并发控制工具&#xff0c;如 mu…

全新AI模型家族登场:完全可复现的开源语言模型OLMo 2

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

探索Python WebSocket新境界:picows库揭秘

文章目录 探索Python WebSocket新境界&#xff1a;picows库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;picows库概述第三部分&#xff1a;安装picows库第四部分&#xff1a;简单库函数使用方法第五部分&#xff1a;场景应用第六部分&#xff1a;常见Bug及解决方案第…

Jenkins Nginx Vue项目自动化部署

目录 一、环境准备 1.1 Jenkins搭建 1.2 NVM和Nodejs安装 1.3 Nginx安装 二、Jenkins配置 2.1 相关插件安装 2.2 全局工具安装 2.3 环境变量配置 2.4 邮箱配置&#xff08;构建后发送邮件&#xff09; 2.5 任务配置 三、Nginx配置 3.1 配置路由转发 四、部署项目 …

《Python语言程序设计》(2018年版)第15遍刷第1章第1题和第2题

2024.11.28 重新开始刷题 第一章 1.1 print( Welcome to Python Welcome to Computer Science Programming is fun )1.2 text_message "Welcome to Python\n"print(text_message * 5)

认识redis 及 Ubuntu安装redis

文章目录 一. redis概念二. redis应用场景二. redis的特性四. 使用Ubuntu安装redis 一. redis概念 redis 是在内存中存储数据的中间件, 用在分布式系统 redis是客户端服务器结构的程序, 客户端服务器之间通过网络来通信 二. redis应用场景 redis可用作数据库 类似MySQL, 但…