Linux☞进程控制

在终端执行命令时,Linux会建立进程,程序执行完,进程会被终止;Linux是一个多任务的OS,允许多个进程并发运行;

Linxu中启动进程的两种途径:

①手动启动(前台进程(命令gedit)...后台进程(命令+‘&’))

②调度启动   --at/cron启动

at执行的命令一般不会在终端回显,可以采用重定向到文件就可以查看;

Linux环境下常见的进程操作命令:

ps--查看系统中的进程;

top--动态显示系统中的进程;

kil--终止进程(包括后台进程);

Linux环境下的进程会有一个唯一的进程标识符(pid),进程标识有进程号PID和它的父进程号PPID,PID唯一标识一个进程,其中,PID和PPID都是非零正整数。获得当前进程的PID和PPID的系统调用是getpid()和getppid()函数【头文件unistd.h】;

ps -ef|grep test1   (可以查找程序test1.c运行时的进程号);

3个特殊进程:

PID为0的调度进程,是内核的一部分,也被称为交换进程和系统进程;

PID为1的init进程(centos6及之前版本),init进程是内核启动并运行的第一个用户进程(不是内核中的系统进程),负责对系统进行初始化,并将系统引导到某个状态。init进程不能被终止

 PID为2的kthreadd内核进程,其是一个内核线程,负责执行后台操作。

进程相关函数: 

exec函数族--在进程中启动另一个程序执行;

system--在进程中开始另一个进程;

fork--从已经存在的进程中复制一个新进程

sleep--让进程暂停运行一段时间;

exit/_exit--用来终止进程

wait/waitpid--暂停父进程,等待子进程完成运行;

Fork函数

 进程调用一次fork函数创建一个新进程,新创建的新进程被称为子进程。该函数调用一次但是返回两次,子进程返回值是0,父进程返回新的子进程的pid。父、子进程并不共享这些存储空间部分,通常父、子进程共享代码段;子进程继承父进程的以下属性:已打开的文件描述符 实际UID、GID,有效UID、GID 当前工作目录 根目录 文件创建UMASK 环境 资源限制

exec函数族

例6-3:用fork函数创建一个子进程,在子进程中。要求显示子进程号和父进程号,然后显示当前目录下的文件信息,在父进程中同样显示子进程号和父进程号;

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
        pid_t result;
        int newret;
        result=fork();
        if(result==-1)
        {
                printf("进程创建失败");
        }else if(result==0)
        {
                printf("返回值是:%d,这是子进程,进程号是:%d\n",result,getpid());
                printf("父进程号是:%d\n",getppid());
                execl("/bin/ls","ls","-l",0);
        }else
        {
                sleep(10);
                printf("返回值是:%d,这是父进程,进程号是:%d\n",result,getpid());
                printf("父进程号是:%d\n",getppid());
        }
}

total后是ls列出的内容,

 exec族的6个函数来建立子进程分别是execl、execv、execle、execve、execlp、execvp函数;其中l、e、v、p表示函数中的参数分别用列表传递方式、字符指针数组传递方式、可指定环境变量及路径自动搜索功能;

exec示例:

char *const ps_argv[]={"ps","-o","pid,ppid,pgrp,session,tpgid,comm",NULL};

char *const ps_envp[]={"PATH=/bin:/user/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);

execlp("ps","ps","-o","pid,ppid,pgrp,session,tpgid,comm",NULL);

execvp("ps",ps_argv);

 exec应用:

1.execv函数的使用,要在程序中执行命令:ps -ef,命令ps在’/bin‘目录下,在这一函数中,参数v表示参数传递(含命令)为构造指针数组方式;

char* arg[]={"ps","-ef",NULL};

函数的使用:

execv("/bin/ps",arg);

【ps命令参数】

-e 显示所有进程(等价于-A)
-f  全部列出,通常和其他选项联用】

//参考程序为:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    char *argv[]={"ps","-ef",NULL};
    execv("/bin/ps",argv);
    return 1;
}

2.execlp函数的使用,在程序中执行命令:ps -ef,命令ps在‘/bin’目录下,在这一函数中,参数l表示命令或参数逐个列举,参数p是文件查找方式(自动检索路径而不需要给出路径),函数调用形式:

execlp("ps","ps","-ef",NULL);

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    execlp("ps","ps","-ef",NULL);
    return 1;
}

3.execl函数应用,在程序中执行命令:ps -ef,命令ps在‘/bin’目录下,在这一函数中,参数l表示命令或参数逐个列举,需要给定路径,函数调用形式如下:

execl("/bin/ps","ps","-ef",NULL);

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    execl("/bin/ps","ps","-ef",NULL);
    return 1;
}

4.execle函数应用,execle("/bin/login","login","-p",username,NULL,envp);上述语句运行时,login提示用户输入密码,输入密码期间关闭终端的回显,然后验证密码的正确性,如果密码不正确,login终止,init会重新fork/exec一个getty进程。如果密码正确,login程序设置一些环境变量,并设置当前的工作目录位用户的主目录;

5.设计程序,在子进程中调用函数execl(''/bin/ps","ps","-ef",NULL),而在父进程中调用函数execle("/bin/env","env",NULL,envp),其中定义:char *envp={"PATH=/tmp","USER=liu",NULL};

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
        char *envp[]={"PATH=/tmp","USER=liu",NULL};
        pid_t result;
        result=fork();
        if(result==-1)
        {
                printf("创建进程失败!\n");
        }else if(result==0)
        {
                printf("创建进程成功\n");
                execl("/bin/ps","ps","-ef",NULL);
        }else
        {
                sleep(5);
                printf("父进程\n");
                execle("/bin/env","env",NULL,envp);
        }
        return 1;
}
//测试程序,先输出“创建进程成功”,之后运行ps- ef命令,停顿5秒后,输出"父进程",显示env命令内容:
PATH=/tmp
USER=liu

进程终止的两种形式:

①正常终止:main返回、调用exit函数、调用_exit系统调用;

②异常终止:被信号终止、调用absort,使其产生SIGABRT信号;

exit函数、_exit系统调用区别:

设计程序使得子进程和父进程在显示输出一些文字后用_exit和exit函数终止进程;

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
        pid_t result;
        result=fork();
        if(result==-1)
        {
                printf("创建进程失败!\n");
                exit(0);
        }else if(result==0)
        {
                printf("测试终止进程的_exit函数\n");
                printf("目前为子进程,这一行我们用缓存!");
                _exit(0);
        }else
        {
                sleep(5);
                printf("测试终止进程的exit函数\n");
                printf("目前为父进程,这一行我们用缓存!");
                exit(0);
        }
        return 1;
}

printf函数使用的是缓冲I/O方式,在遇到‘\n’换行符时,自动将缓冲区的记录读出;在调用exit函数时,会先调用退出处理函数,然后清理I/O缓冲区,最后执行exit系统调用,而_exit函数则是直接调用exit系统调用,因此无法正常输出缓冲区的内容;

如果在子进程中调用sleep(5),父进程不调用会出现:

XXX

僵尸进程

一个已经终止运行、但其父进程还没对其进行善后处理(获得终止子进程的有关信息、释放它所占有的资源)的进程;

使用fork创建的子进程,在父进程已经结束,但其还在继续运行,子进程进入无父进程的状态,称之为孤儿进程;孤儿进程会很快被init/systemd所收养;另外,为避免这种情况,可以通过在父进程中调用wait函数/waitpid函数,使得子进程比父进程早终止;

示例:僵尸进程的产生

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
        pid_t result;
        result=fork();
        if(result==-1)
        {
                printf("创建进程失败!\n");
                exit(0);
        }else if(result==0)
        {
                printf("这是子进程,进程号是:%d\n",getpid());
        }else
        {
                wait(NULL);  //init系统消除僵尸进程;
                sleep(20);
                printf("这是父进程,进程号是:%d\n",getpid());
        }
        return 1;
}

一个程序退出时,它的子进程会被init进程继承,它是Linux启动后的第一个进程,init进程会自动清理所有它所继承的僵尸进程。

例:在父进程中调用wait函数等待子进程,父进程直到接收到子进程结束的信号后,父进程结束等待。设计一个程序,要求创建一个子进程,子进程显示自己的进程号pid后暂停一段时间,父进程等待子进程正常结束,打印显示等待的进程号pid和等待的进程退出状态。

//待定

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

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

相关文章

How to: Build a Custom End-User Skin Selector

This section explains how to populate a ComboBoxEdit control with DevExpress skin items. 本节介绍如何使用DevExpress皮肤项填充ComboBoxEdit控件。 To populate a combo box editor, iterate through the SkinManager.Skins collection, which returns all currently a…

搜索引擎优化服务如何寻找?

首先你要了解搜索引擎优化&#xff0c;也就是seo具体是什么&#xff0c;要做些什么&#xff0c;然后就是确定你自身业务的需求&#xff0c;是要特定的关键词排名&#xff0c;还是整体网站流量的提升&#xff0c;还是想要优化目前的网站 接下来你就可以正式的寻找真正能帮助到你…

详解大厂实时数仓建设V4.0

一、实时数仓建设背景 1. 实时需求日趋迫切 目前各大公司的产品需求和内部决策对于数据实时性的要求越来越迫切&#xff0c;需要实时数仓的能力来赋能。传统离线数仓的数据时效性是 T1&#xff0c;调度频率以天为单位&#xff0c;无法支撑实时场景的数据需求。即使能将调度频…

【Linux】进程间通信之匿名管道

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

【启程Golang之旅】让文件操作变得简单

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

【python解决】查询报%d format: a number is required, not str问题

【Python解决】查询报%d format: a number is required, not str问题 在Python中&#xff0c;字符串格式化是一种常见的操作&#xff0c;用于创建包含变量的字符串。如果你在使用%操作符进行格式化时遇到了%d format: a number is required, not str的错误&#xff0c;这意味着…

计算机缺失msvcp100.dll如何解决?教你5种简单高效的修复方法

在现代科技发展的时代&#xff0c;计算机已经成为我们生活和工作中不可或缺的工具。然而&#xff0c;在使用计算机的过程中&#xff0c;我们常常会遇到各种问题和困扰。其中之一就是计算机找不到msvcp100.dll文件。这个问题可能会给我们的生活和工作带来很多不便&#xff0c;下…

插入排序和希尔排序详解

插入排序详见&#xff1a;点这里 希尔排序(Shells Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。其是基于插入排序改进而来的。 希尔排序大致分为两步预排序和插入排序两大步。 预排序是将变量分为 n…

Docker大学生看了都会系列(八、Dokcerfile部署go项目)

系列文章目录 第一章 Docker介绍 第二章 2.1 Mac通过Homebrew安装Docker 第二章 2.2 CentOS安装Docker 第三章 Docker常用命令 第四章 常用命令实战 第五章 Docker镜像详解 第六章 Docker容器数据卷 第七章 Dockerfile详解 第八章 Dokcerfile部署go项目 文章目录 一、前言二、环…

【Vue】面经基础版-案例效果分析

面经效果演示 功能分析 通过演示效果发现&#xff0c;主要的功能页面有两个&#xff0c;一个是列表页&#xff0c;一个是详情页&#xff0c;并且在列表页点击时可以跳转到详情页底部导航可以来回切换&#xff0c;并且切换时&#xff0c;只有上面的主题内容在动态渲染 实现思路…

【Vue】练习-Vuex中的值和组件中的input双向绑定

目标 实时输入&#xff0c;实时更新&#xff0c;巩固 mutations 传参语法 实现步骤 代码示例 App.vue <input :value"count" input"handleInput" type"text"> <script>export default {methods: {handleInput (e) {// 1. 实时获取…

【学习笔记】Windows GDI绘图(十)Graphics详解(中)

文章目录 Graphics的方法AddMetafileComment添加注释BeginContainer和EndContainer新建、还原图形容器不指定指定源与目标矩形指定源与目标矩形 Clear清空并填充指定颜色CopyFromScreen截图CopyPixelOperation DrawImage绘制图像DrawImage的GraphicsDrawImageAbort回调ExcludeC…

NSSCTF中的popchains、level-up、 What is Web、 Interesting_http、 BabyUpload

目录 [NISACTF 2022]popchains [NISACTF 2022]level-up [HNCTF 2022 Week1]What is Web [HNCTF 2022 Week1]Interesting_http [GXYCTF 2019]BabyUpload 今日总结&#xff1a; [NISACTF 2022]popchains 审计可以构造pop链的代码 <php class Road_is_Long{public $…

桑基图Cannot set properties of undefined (setting ‘dataIndex‘)

前端写桑基图的时候碰到以上bug 原因是&#xff1a; 桑基图中的name值有重复的&#xff0c;把重复的name值去掉就好了&#xff0c;或者如果name排查太麻烦&#xff0c;可以用唯一id作为name,增加些字段&#xff0c;展示时用fomatter的方式 参照https://www.cnblogs.com/lempe…

详解FedAvg:联邦学习的开山之作

FedAvg&#xff1a;2017年 开山之作 论文地址&#xff1a;https://proceedings.mlr.press/v54/mcmahan17a/mcmahan17a.pdf 源码地址&#xff1a;https://github.com/shaoxiongji/federated-learning 针对的问题&#xff1a;移动设备中有大量的数据&#xff0c;但显然我们不能收…

GPT-4o仅排第二!北大港大等6所高校联手,发布权威多模态大模型榜单!

多模态大模型视频分析能力榜单出炉&#xff1a; Gemini 1.5 Pro最强&#xff0c;GPT-4o仅排第二&#xff1f; 曾经红极一时的GPT-4V屈居第三。 3.5研究测试&#xff1a;hujiaoai.cn 4研究测试&#xff1a;askmanyai.cn Claude-3研究测试&#xff1a;hiclaude3.com 最近&#…

python代码中参数的默认值

python中的函数&#xff0c;可以给形参指定默认值。 带有默认值的参数&#xff0c;可以在调用的时候不传参。 如上图所示&#xff0c;在给函数设定形参的时候可以给函数形参设定默认值&#xff0c;当然默认参数的形参应该在非默认形参的后面。 如果在调用函数的时候&#xff…

【机器学习】因TensorFlow所适配的numpy版本不适配,用anaconda降低numpy的版本

目录 0 TensorFlow最高支持的numpy版本 1 激活你的环境&#xff08;如果你正在使用特定的环境&#xff09; 2 查找可用的NumPy版本 3 安装特定版本的NumPy 4. 验证安装 5.&#xff08;可选&#xff09;如果你更改了base环境 0 TensorFlow最高支持的numpy版本 要使用 …

测试基础11:测试用例设计方法-等价类划分

课程大纲 1、概述 1.1测试用例设计方法意义 穷举测试&#xff1a;每种输入都测一次。最完备&#xff0c;但不现实。 使用设计方法&#xff0c;用最少的数据&#xff08;成本&#xff09;&#xff0c;实现最大的测试覆盖。 1.2常用设计方法 ①等价类划分 ②边界值分析 ③错误推…

SpringBoot+Vue网上购物商城系统(前后端分离)

技术栈 JavaSpringBootMavenMySQLMyBatisVueShiroElement-UI 系统角色对应功能 用户商家管理员 系统功能截图