Linux进程基础

news2024/9/22 19:33:20

进程指正在运行的程序,如下图示,是资源分配的最小单位,可以通过“ps ”或“top”等命令查看正 在运行的进程,线程是系统的最小调度单位,一个进程可以拥有多个线程,同一进程里的线程可以共享此 进程的同一资源

 每个进程都有一个唯一的标识符,既进程 ID,简称 pid

进程间的通信的几种方法?

1 管道通信:有名管道,无名管道

2 信号通信:信号的发送,信号的接受,信号的处理

3 IPC 通信:共享内存,消息队列,信号量 

4 Socket 通信

进程的三种基本状态以及转换

 进程创建

所有的进程都是由其他进程创建(除了 pid 为 0 号的 idle 进程),pid 号为 1 的 init 进程是系统启动后 运行的第一个进程,是所有进程的父进程,init 进程会初始化一部分系统服务,创建其他进程。

创建新进程的那个进程称为父进程,新进程称为子进程,父进程和子进程拥有相同的代码段数据段, 有各自独立的地址空间。采用写时拷贝技术,即创建的新进程不会立即把父进程的资源空间复制过来,只 有在修改时才会复制资源,另外父进程挂起的信号和文件锁不会被子进程继承。

子进程结束后,它的父进程要回收它的资源,否则就会成为僵尸进程 。

如果父进程先结束,子进程会被 init 进程收养,称为孤儿进程

创建进程常用函数如下定义:

 实验代码

在程序中,父进程中创建一个子进程。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
    pid_t pid;
    int i = 1;
     
    pid = fork();
    if(pid > 0)   //父进程
    {
       printf("this is  child  pid: %d   parent pid: %d\n",getpid(),getppid()); 
       printf("parent data: %d \n",i);

    }else if (pid  == 0)  //子进程
    {   
        //sleep(1);   //先运行父进程
        printf("this is  child  pid: %d\n",getpid());
        printf("child data: %d \n",i);
      

    }else if (pid < 0)
    {
        printf("cread failed\n");
        return -1;
    }
    
  
    return 0;
}

在 Ubuntu 上编译运行,打印进程号如下图所示:

 

exec 函数

用 fork 函数创建子进程后,子进程往往要调用一种 exec 函数以执行另一个程序,该子进程被新的程序 替换,改变地址空间,进程映像和一些属性,但是 pid 号不变。

exec 函数详解如下表所示:

 以下函数都是根据 execve 实现

int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

实验代码:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int main(int argc, char const *argv[])
{
    pid_t pid;
    char *arr[] = {"ls","-l",NULL};
    
    /*exec族函数
    int execl(const char *path, const char *arg, ... );
    int execv(const char *path, char *const argv[]);
    */
  
    pid = fork();
    if(pid > 0)   //子进程
    {
       printf("this is  parent  pid: %d\n",getpid());
       wait(NULL);     //回收子进程

    }else if (pid  == 0)  //父进程
    {   
        //sleep(1);   //先运行子进程
        printf("this is  child  pid: %d  parent pid: %d\n",getpid(),getppid()); 
        //execl("/bin/ls","ls","-l",NULL);
        execv("/bin/ls",arr);      
        exit(-1);
        

    }else if (pid < 0)
    {
        printf("cread failed\n");
        return -1;
    }
    
  
    return 0;
}

执行结果

 

 ps 和 kill 命令

ps 命令:ps 命令可以列出系统中当前运行的那些进程。

命令格式:ps [参数]

命令功能:用来显示当前进程的状态

常用参数: aux

kill 命令:kill 命令用来杀死进程 举例:kill -9(SIGKILL) PI

进程的状态:

D: 无法中断的休眠状态 (通常 IO 的进程)

R: 正在执行中

S: 静止状态

T: 暂停执行

Z: 不存在但暂时无法消除

W: 没有足够的记忆体分页可分配 <: 高优先序的行程

N: 低优先序的行程

L: 有记忆体分页分配并锁在记忆体内 (实时系统或捱 A I/O)

如下所示,使用命令“ps aux | grep a.out”查找到./a.out 的进程号为 3179,然后输入“kill -9 3179”结 束此进程,

 

孤儿进程与僵尸进程:

孤儿进程:父进程结束以后,子进程还未结束,这个子进程就叫做孤儿进程。

僵尸进程:子进程结束以后,父进程还在运行,但是父进程不去释放进程控制块,这个子进程就叫做僵尸 进程。

实验代码 在程序中,创建的子进程变为孤儿进程:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
    int i=0;
    pid_t pid;
    // 创建一个子进程
    pid = fork();
    if (pid < 0)
    {
        printf("fork is error \n");
        return -1;
    }
    //父进程 让父进程先结束,并打印进程 PID
    if (pid > 0)
    {
      printf("pid is %d\n", getpid());
    }
    //子进程,让子进程等待一会,让父进程先结束,并打印子进程的父进程的 pid
    if (pid == 0)
    {
        sleep(2);
        printf("parent pid is %d\n", getppid());
    }
    return 0;
}

编译运行,如下图所示:

 如上图所示,子进程中打印的父进程的进程号和父进程的进程号是不一样的,说明创建的子进程变成 了孤儿进程,此进程被系统的 init 进程"领养"了。

 实验代码 在程序中,子进程变为僵尸进程:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
    int i=0;
    pid_t pid;
// 创建一个子进程
    pid = fork();
    if (pid < 0)
    {
        printf("fork is error \n");
        return -1;
    }
    //父进程 让父进程先结束,并打印进程 PI
    if (pid > 0)
    {
    while(1);
    }
    //子进程,让子进程先结束
    if (pid == 0)
    {
        printf("This is child\n");
        exit(0);
    }
    return 0;
}

编译运行,如下图所示:

再打开另一个终端,查看此进程如下图所示为僵尸进程。 

 

wait()函数

wait()函数一般用在父进程中等待回收子进程的资源,而防止僵尸进程的产生。

 与 wait 函数的参数有关的俩个宏定义:

WIFEXITED(status):如果子进程正常退出,则该宏定义为真

WEXITSTATUS(status):如果子进程正常退出,则该宏定义的值为子进程的退出值。

实验代码:

在程序中,使用 wait()函数,防止僵尸进程的产生

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>


int main(int argc, char const *argv[])
{
    pid_t pid;
    int start; 
    pid = fork();
    //让父进程先运行,没有时间去释放进程控制快
    if(pid > 0)  //父进程
    {   
         pid = wait(&start);
         if (WIFEXITED(start) == 1)   //正常退出为真
         {
           printf("return value is %d\n",WEXITSTATUS(start));
         }
         
    }
    //让子进程先结束
    else if (pid == 0)   //子进程
    {   
       sleep(2);
       printf("this is child\n");
       printf("child pid:%d\n",getpid());
       exit(0);  //对应WEXITSTATUS(start)的退出值
    }
    else if (pid < 0)
    {
       printf("cread fork faile\n");
       exit(-1);
    }
    
    
    
    return 0;
}

编译运行,如下图所示:

 

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

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

相关文章

Server版支持即将到期,Jira和Confluence如何迁移?(2)

到2024年2月&#xff0c;Atlassian将终止对Server产品及插件的所有支持。是时候制定您的迁移计划了——Atlassian为您提供两种迁移选择&#xff0c;一是本地部署的数据中心版本&#xff0c;中国用户25人以上即可使用&#xff0c;二是云版。作为Atlassian全球白金合作伙伴&#…

Markdown可以在线编辑吗?这个办法很好用

Markdown是一种轻量级标记语言&#xff0c;它使用简单的语法来创建文本&#xff0c;非常易于学习。它最初被设计为一种用于写作的格式&#xff0c;但现在已经成为了一种非常受欢迎的文本编辑工具。 作为一个较为方便的在线文本编辑器&#xff0c;它可以用代码代替文字&#xf…

一篇完整的测试方案怎么写

看上面的目录&#xff0c;详细 文档说明 文档名称 创建人/修改人 版本 时间 备注 v1.0 2022-11-17 新建 v1.1 2022-11-25 v1.2 2022-12-05 v2.0 2022-12-13 v2.1 2022-12-14 一、文档目的 为软件开发项目管理者、软件工程师、系统维护工程师、测试…

如何开发合成物品功能?

UE5 插件开发指南 前言0 数据结构1 合成面板UI组件2 小结前言 现在策划有一个合成物品的需求:可以将多个低级物品合成高级物品,如果背包中已有低级物品了,合成时需要减掉物品的费用,只需要支付合成费;提供玩家一个合成物品的层级视图,以便于玩家有节奏的购买物品,如下图…

电影《刀剑神域进击篇:暮色黄昏》观后感

上周看了电影《刀剑神域进击篇&#xff1a;暮色黄昏》&#xff0c;刀剑神域系列质量还是非常不错的&#xff0c; 本部电影讲述主角团队攻克boss&#xff0c;阻止公会团体互相打架的故事。 刀剑系列&#xff0c;记得当初是以一部连载动漫为开端&#xff0c;如果不是特别喜欢看动…

计算机网络—HTTP基本概念、HTTPS、HTTP状态码、HTTP缓存、HTTP请求

参考小林coding HTTP基本概念 HTTP是超文本传输协议。所谓的超文本&#xff0c;就是超越了普通文本的文本&#xff0c;最关键的是有超链接&#xff0c;能从一个超文本跳转到另一个超文本。 HTML是最常见的超文本&#xff0c;本身是纯文字文件&#xff0c;但是内部使用很多标签…

Scrum敏捷项目管理实例

这是一个Scrum敏捷单团队敏捷开发示例。 1、建立产品路线图 首先我们需要为这个项目创建一个产品路线图&#xff0c;产品路线图是一个高层次的战略计划&#xff0c;它描述了产品在未来一段时间可能会如何发展和壮大&#xff0c;产品路线图确保整个产品团队持续关注产品的目标…

GEE:对Landsat遥感影像进行处理,水体提取与可视化

作者:CSDN @ _养乐多_ 本文介绍了通过Google Earth Engine平台,并使用Landsat卫星遥感数据提取水体掩膜的方法和代码。通过裁剪和去除云等处理步骤,最终得到具有水体掩膜的影像,并进行可视化和导出。这种方法基于归一化水体指数(MNDWI)和OTSU阈值计算技术,使用了一个自…

MyBatis(MyBatis环境搭建,单表操作)

目录 MyBatis 环境搭建 1.添加 Mybatis 框架支持 2.设置 MyBatis 配置信息 2.1.设置数据库连接的相关信息 2.2 Mybatis xml 保存路径和 xml命名格式 ​编辑 MyBatis 模式开发 Mybatis xml 模板 查询表内容 单元测试 以根据id,查询用户对象这个方法为例 获取动态参数的…

警惕,最近的副业兼职诈骗。

大家好&#xff0c;我是鸟哥。 今天和大家聊聊最近超级猖狂的几类诈骗。 一、副业诈骗。最近两年“副业刚需”这个口号很流行&#xff0c;尤其是今年&#xff0c;职场动荡、工作难找&#xff0c;副业刚需变成了副业焦虑&#xff0c;骗子们也正是抓住了大家的这个心理&#xf…

【Vue全家桶实现电商系统】— VSCode配置Git(二)

【Vue全家桶实现电商系统】— VSCode配置Git&#xff08;二&#xff09; 当我们在VScode中编写代码后&#xff0c;需要提交到git仓库时&#xff0c;但是我们又不想切换到git的命令行窗口&#xff0c;我们可以在 VScode中配置git&#xff0c;然后就可以很方便快捷的把代码提交…

JavaScript中的Hook技术:特性、优点、缺点和使用场景

引言&#xff1a; 随着JavaScript的不断发展&#xff0c;开发者们正在寻找更灵活和可扩展的方式来修改或扩展现有的代码。其中一种广泛应用的技术是"Hook"&#xff0c;它允许开发者拦截和修改现有的函数或方法的行为。本文将详细介绍JavaScript中的Hook技术&#xf…

软件确认测试、验收测试和系统测试有什么区别和联系?

软件确认测试、验收测试和系统测试都是软件测试过程中的重要环节&#xff0c;它们各自有不同的测试侧重点和目标&#xff0c;但也有一些联系。 1、软件确认测试 称为单元测试或白盒测试&#xff0c;是对软件中各个模块的基本功能进行测试的一种测试方式&#xff0c;主要使用…

【Python从入门到进阶】22、urllib库基本使用

接上篇《21、爬虫相关概念介绍》 上一篇我们介绍了爬虫的相关概念&#xff0c;本篇我们来介绍一下用Python实现爬虫的必备基础&#xff0c;urllib库的学习。 一、Python库的概念 我们今后的学习可能需要用到很多python库&#xff08;library&#xff09;&#xff0c;及引用其…

在阿里外包干了3个月,我果断跑路了

有一种打工人的羡慕&#xff0c;叫做“大厂”。 真是年少不知大厂香&#xff0c;错把青春插稻秧。 但是&#xff0c;在深圳有一群比大厂员工更庞大的群体&#xff0c;他们顶着大厂的“名”&#xff0c;做着大厂的工作&#xff0c;还可以享受大厂的伙食&#xff0c;却没有大厂…

Python接口自动化脚本持续集成过程

之前都是开发人员提交代码到git&#xff0c;触发jenkins拉取git上面的代码并进行编译部署&#xff0c;部署成功后测试人员就可以在浏览器端开始测试了。 作为测试人员&#xff0c;也有跟git和jenkins打交道的时候。 项目实践&#xff1a; python接口自动化脚本编写成功后&am…

图解LeetCode——102. 二叉树的层序遍历

一、题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 二、示例 2.1> 示例 1&#xff1a; 【输入】root [3,9,20,null,null,15,7] 【输出】[[3],[9,20],[15,7]] 2.2> 示例…

Redis7实战加面试题-高阶篇(手写Redis分布式锁)

手写Redis分布式锁 面试题&#xff1a; 1.Redis除了拿来做缓存&#xff0c;你还见过基于Redis的什么用法? 数据共享&#xff0c;分布式session分布式锁 全局ID 计算器、点赞位统计 购物车 轻量级消息队列&#xff08;list&#xff0c;stream&#xff09; 抽奖 点赞、签到、打…

功率信号源驱动电路工作原理是什么

功率信号源驱动电路是一种能够将低功率、微弱的信号放大到足够高的功率水平的电路。在现代通信、医疗、工业等领域中&#xff0c;功率信号源驱动电路被广泛应用。下面&#xff0c;我们将对功率信号源驱动电路进行详细的介绍。 图&#xff1a;ATG-2000系列功率信号源 功率信号源…

【大数据学习篇12】 Spark项目实战-数据可视化

学习目标/Target 了解数据可视化系统架构 掌握Phoenix集成HBase 熟悉建立Phoenix与HBase表映射 了解Spring Boot项目的创建 掌握Java Web项目中实体类的创建 掌握Java Web项目中数据库访问接口的创建 掌握Java Web项目中控制器类的创建 熟悉Java Web项目中HTML页面的创建…