【Linux】孤儿进程 | 环境变量 | 命令行参数 | 进程优先级

news2024/12/21 8:03:46

文章目录

  • 1. 孤儿进程
  • 2. 环境变量
    • 1. PATH环境变量
      • 证明ls是系统指令
      • 修改自己写的可执行程序对应路径
    • 2. env——查看系统环境变量
    • 3. 获取环境变量
      • envp
      • environ
      • getenv 函数获取 (主流)
    • 4. 总结
  • 3 . 命令行参数
      • 理解命令行参数
  • 4. 进程优先级
    • 优先级与权限的区分
    • 为什么会有优先级?
    • 查看系统进程的优先级
    • 调整进程优先级

1. 孤儿进程

如果父进程一直存在,子进程先退出了,父进程对子进程退出不管不顾,会出现什么样问题么?


创建makefile并输入以下内容

   mytest:test.c
  2   gcc -o $@ $^ 
  3 .PHONY:clean
  4 clean:
  5   rm -f mytest 

mytest 属于 目标文件
test.c 属于 依赖文件列表
$@代表目标文件
$^ 代表依赖文件列表


创建test.c并输入以下内容

 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   pid_t id=fork();
  6   if(id==0)
  7   {
  8     //子进程
  9     while(1)
 10     {
 11     printf("我是子进程,我的pid是:%d,我的ppid是%d",getpid(),getppid());
 12     sleep(1);                                                                             
 13     }                                                                                                                                                                
 14     
 15   }
 16   else if(id>0)
 17   {
 18    //父进程
 19    int count=0;//父进程只运行10次
 20     while(1)                        
 21     {                               
 22     printf("我是父进程,我的pid是:%d,我的ppid是%d",getpid(),getppid());
 23     sleep(1);                       
 24     if(count--<=0)                  
 25     {                               
 26       break;                        
 27     }                                                                                                                                      
 28     }                                                                                                                                      
 29   }                                                                                                                                        
 30 }                                         
  • 使子进程一直循环,父进程只运行10次

复制SSH渠道,创建终端2,在保证终端1mytest运行的情况下,在终端2中输入指令
while :; do ps axj | head -1 && ps axj | grep mytest | grep -v grep ; sleep 1; echo "---------"; done

创建终端方法点击查看


---------
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
17835 27831 27831 17835 pts/0    27831 S+    1002   0:00 ./mytest
27831 27832 27831 17835 pts/0    27831 S+    1002   0:00 ./mytest

当父子进程刚开始共存时,两者状态都是S+


PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    1 27832 27831 17835 pts/0    17835 S     1002   0:00 ./mytest

当父进程运行结束后,子进程状态为S


正常来说,若父子进程中子进程结束,父进程要接收子进程的退出码结果,所以子进程处于僵尸状态
但是 父子进程中父进程结束,为什么父进程没有进入僵尸状态呢?

  • 当前退出的进程27831的父进程是bash,bash会自动回收27831的僵尸状态
  • 原本进程27832的父进程是27831,当27831进程结束后,27832的父进程变为1
  • 如果父子进程中父进程先退出,而子进程没退出,子进程在父进程退出后,要被1号进程领养,1号进程称为操作系统,而被领养的进程称为孤儿进程
  • 如果不领养,子进程后续退出,就无人回收了

2. 环境变量

在操作系统当中由系统在开机之后帮我们维护的一些系统运行时的动态参数


我们自己写的代码,编译之后,运行的时候,为什么要带 ./ ?

  • . 代表当前路径 , / 代表路径分割符 . / 可执行程序说明使用相对路径的方式来定位可执行程序
  • 自己写的可执行程序和系统自带的指令之间没有区别

那为什么运行系统的指令不需要 ./ ?

  • 因为系统指令的路径在环境变量中

1. PATH环境变量

echo 作为打印字符串的一条命令

[yzq@VM-8-8-centos ~]$ echo abcd   
abcd


echo $PATH 查看环境变量PATH

[yzq@VM-8-8-centos ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/mydir/.local/bin:/home/mydir/bin

/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/mydir/.local/bin:/home/mydir/bin
是以冒号作为分隔符,可以分割出来若干子路径

  • pwd、ls指令,会在环境变量所指明的若干路径中一个个去找,找到就会自动执行,不用带路径
  • 而我们自己实现的可执行程序,路径不在环境变量里,所以必须由用户自动指明它的路径

证明ls是系统指令

使用which 指令,搜索特定指令所对应的路径

[yzq@VM-8-8-centos my]$ which ls
alias ls='ls --color=auto'
    /usr/bin/ls

ls的路径为 /usr/bin/ls
环境变量是从左到右,一条一条去查找,只要找到就停下来
ls指令在环境变量的usr/bin 路径下,说明 ls 指令不用带路径

修改自己写的可执行程序对应路径

修改自己写的可执行程序的路径,让其不用添加路径即可运行


创建test.c文件

#include<stdio.h>
  2 int main()
  3 {
  4   printf("hello");                                                                                                                                                   
  5 }                                                                                                                         
       

输入 gcc -o testc test.c ,生成testc可执行程序
输入 which testc ,查询testc的路径

[yzq@VM-8-8-centos my]$ which testc
/usr/bin/which: no testc in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/mydir/.local/bin:/home/mydir/bin)

说明 testc路径不在环境变量中


使用pwd ,查询当前testc的路径,
输入 export PATH=$PATH: 当前路径 ,将testc的路径新增到到环境变量中

[yzq@VM-8-8-centos my]$ pwd
/home/mydir/my
[yzq@VM-8-8-centos my]$ export PATH=$PATH:/home/mydir/my


[yzq@VM-8-8-centos my]$ testc
hello

直接 使用 testc ,就运行可执行程序

2. env——查看系统环境变量

使用 env ,会出现如下环境变量
在这里插入图片描述

这些环境变量都是用户登录的时候设置好的,都是kv的


输入 echo $HOSTNAME 显示当前机器 名字

[yzq@VM-8-8-centos ~]$ echo $HOSTNAME
VM-8-8-centos


输入 echo $SHELL 显示当前所使用的shell

[yzq@VM-8-8-centos ~]$ echo $SHELL
/bin/bash

输入 echo $HOME,当前为普通用户

[yzq@VM-8-8-centos ~]$ echo $HOME
/home/mydir

HOME环境变量表示当前用户所对应的家目录


切换成root用户后, 此时对应root目录

[root@VM-8-8-centos mydir]# echo $HOME
/root

对于不同登录的人,同一个环境变量里面放的不同的内容,所以环境变量是针对特定的人在特定的场景使用的

3. 获取环境变量

envp

main函数可以带3个参数分别为 int argc 和 char*argv [ ] 和char * envp[ ] (环境变量表)

  • char* envp[ ]是一个指针数组,char类型指针都指向字符串,但最后无效内容必须以NULL结尾

创建test.c文件

#include<stdio.h>
    2 #include<unistd.h>
    3 int main(int argc,char*argv[],char*envp[])
    4 {
    5   int i=0;
    6   for(i=0;envp[i];i++)
    7   {
    8     printf("envp[%d]->%s\n",i,envp[i]);
    9   }                                                                                                                                                                
   10 }   

创建makefile

   mytest:test.c
  2   gcc -o mytest test.c
  3 .PHONY:clean
  4 clean:
  5   rm -f mytest  

输入 make ,使用./mytest 执行可执行程序


发现envp是一张传递给当前进程的环境变量表
char类型指针指向环境变量字符串

environ

若main函数不传参数,还想要拿到环境变量,可以使用 environ


修改test.c文件

 #include<stdio.h>
    2 #include<unistd.h>
    3 int main()
    4 {
    5   extern char** environ;//声明
    6   int i=0;
    7   for(i=0;environ[i];i++)
    8   {
    9     printf("environ[%d]->%s\n",i,environ[i]);
    10   }                                                                                                                                                                
    11 }                                                                                              
       

使用make, ./mytest执行可执行程序后

使用environ 也可以拿到所有环境变量

getenv 函数获取 (主流)

char* getenv(const char* name);


修改test.c文件

  1 #include<stdio.h>
    2 #include<stdlib.h>
    3 #include<unistd.h>
    4 int main()
    5 {
    6   char*user=getenv("USER");
    7   if(user==NULL)
    8   {
    9     perror("getenv");
   10   }
   11   else 
   12   {
   13     printf("USER:%s\n",user);
   14   }
   15 }   

输入 make, ./mytest 执行可执行程序

[yzq@VM-8-8-centos my]$ ./mytest
USER:yzq

获取到user的名称

4. 总结

  • 环境变量本质就是一个内存级的一张表,这张表由用户在登录系统的时候,进行给特定用户形成属于自己的环境变量表
  • 环境变量每一个都有自己的用途,有的是进行路径查找的,有的是进行身份认证的,有的是动态库查找的,有的用来进行确认当前路径的等等,每一个环境变量都有自己的应用场景,每一个元素都是kv的

环境变量对应的数据,是从系统的相关配置文件中读取进来的
使用 cd ~ ,进入当前目录的主目录中
使用 ls -la , 显示隐藏文件
在这里插入图片描述
这是两个shell脚本,内部包含了配置文件

3 . 命令行参数

main函数的两个参数,char* argv[] 为指针数组 ,argv为一张表,包含一个个指针,指针指向字符串
int argc,argc为数组的元素个数


修改test.c文件

 #include<stdio.h>
    2 #include<stdlib.h>
    #inlcude<string.h>
    3 #include<unistd.h>
    4 int main (int argc,char*argv[])
    5 {
        int i=0;
    6   for(i=0;i<argc;i++)
    7   {
    8     printf("argv[%d]->%s\n",i,argv[i]);
                                                                                                                                                                                  
   10   }


使用make , ./mytest 执行可执行程序

[yzq@VM-8-8-centos my]$ ./mytest
argv[0]->./mytest
[yzq@VM-8-8-centos my]$ ./mytest -a
argv[0]->./mytest
argv[1]->-a
[yzq@VM-8-8-centos my]$ ./mytest -a -b
argv[0]->./mytest
argv[1]->-a
argv[2]->-b

./mytest -a -b,就是一个字符串
以空格作为分隔符,形成一个一个的子串
第一个./mytest为可执行程序,剩余的统称为参数选项

理解命令行参数

修改test.c文件

      #include<stdio.h>
    2 #include<stdlib.h>
    3 #include<unistd.h>
    4 #include<string.h>
    5 void usage(const char*name)
    6 {
    7   printf("\nusage:%s-[a|b|c]\n\n",name);
    8   exit(0);//终止进程
    9 }                                                                                                                                                                
   10 int main  (int argc,char*argv[])                                                                                                                                 
   11 {                                                                                                                                                                
   12   if(argc!=2)                                                                                                                                                    
   13   {                                                                                                                                                              
   14     usage(argv[0]);//argv[0]代表可执行程序  
        }                                                                                                      }                                                                                                                     
   15     if(strcmp(argv[1],"-a")==0)                                                                                                                                  
   16     {                                                                                                                                                            
   17         printf("打印目录下的文件名\n");                                                                                                                          
   18     }                                                                                                                                                            
   19     else if(strcmp(argv[1],"-b")==0)                                                                                                                          
   20     {                                                                                                                                                            
   21       printf("打印目录下的文件的详细信息\n");                                                                                                                    
   22     }                                                                                                                                                            
   23     else if(strcmp(argv[1],"-c")==0)                                                                                                                             
   24     {                                                                                                                                                            
   25       printf("打印目录下文件的隐藏信息\n");
   26     }
   27     else 
   28     {
   29       printf("待未开发\\n");
   30     }
   31                                                                                                                                                                                 
   32 }                       

使用 make ,./mytest 执行可执行程序

[yzq@VM-8-8-centos my]$ ./mytest

usage:./mytest-[a|b|c]

[yzq@VM-8-8-centos my]$ ./mytest -a
打印目录下的文件名
[yzq@VM-8-8-centos my]$ ./mytest -b
打印目录下的文件的详细信息
[yzq@VM-8-8-centos my]$ ./mytest -c
打印目录下文件的隐藏信息
[yzq@VM-8-8-centos my]$ ./mytest -d
待未开发

相当于使用ls 、ls -l 、ls -la 指令,选项以字符串形式以命令行参数传递给了程序,程序内部对选项做判断,就可使同样的ls ,携带不同的选项,就可表现不同的现象

4. 进程优先级

优先级与权限的区分

权限代表能不能的问题,优先级代表已经能,谁先谁后的问题
比如 权限:若你考完试,你能够自己去老师教室翻阅自己的卷子么,当然不能,没有权限
优先级:若你在食堂排队,你可以打饭,但是有先后顺序


为什么会有优先级?

  • CPU资源有限,一般来说,一个电脑中CPU有一个或者两个,但是进程却有很多个,以少量的资源来应对多量的进程,势必就会存在多进程竞争资源的情况,只要竞争就要确认谁先谁后,确认优先级

查看系统进程的优先级

ps -l 查看当前系统的进程优先级

[yzq@VM-8-8-centos my]$ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 R  1002  3722 17835  0  80   0 - 38324 -      pts/0    00:00:00 ps
0 S  1002 17835 17834  0  80   0 - 29280 do_wai pts/0    00:00:00 bash

PRI代表当前进程的优先级
NI代表当前进程优先级的修正数据
UID代表当前用户的身份标识

PRI数字值越小,优先级越高
PRI(new)=PRI(old)+NI(nice)
一般调整的是nice值,nice值取值范围是[-20-19]
调度器的作用是一碗水端平,让每一个进程有享有资源,所以不支持将一个进程的PRI调整过小,从而导致优先级过高

调整进程优先级

在test.c中修改为以下内容

#include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   while(1)
  6   {
  7     printf(".");
  8     fflush(stdout);//刷新缓冲区
  9     sleep(1);                                                                  
 10   }                                                            
 11   return 0;                                                    
 12 }                                                              
     

使用./mytest运行程序,并复制SSH渠道 创建终端2

在保证终端1mytest运行的情况下,在终端2中使用 ps -la ,找到mytest进程

[yzq@VM-8-8-centos my]$ ps -la
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1002  8561 17835  0  80   0 -  1054 hrtime pts/0    00:00:00 mytest
0 R  1002  9135 23362  0  80   0 - 38332 -      pts/1    00:00:00 ps


再次在终端2中使用 top 指令,输入 r(renice),出现如下数据

PID to renice [default pid = 7429] 

在上一步输入的 ps -la指令中查询mytest的PID

在这里插入图片描述


使用q退出
再次输入 ps -la指令

[yzq@VM-8-8-centos my]$ ps -la
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1002  8561 17835  0  90  10 -  1054 hrtime pts/0    00:00:00 mytest
0 R  1002 12141 23362  0  80   0 - 38332 -      pts/1    00:00:00 ps

发现刚刚修改nice值为10 ,PID值变为90

在这里插入图片描述

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

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

相关文章

Android 动态切换应用图标方案

经常听到大家讨论类似的需求&#xff0c;怀疑大厂是不是用了此方案&#xff0c;据我个人了解&#xff0c;多数头部 app 其实都是发版来更新节假日的 icon。当然本方案也是一种可选的方案&#xff0c;以前我也调研过&#xff0c;存在问题和作者所述差不多&#xff0c;此外原文链…

使用Pyparsing为嵌入式开发定义自己的脚本语言

Python在嵌入式开发中也很流行生成实用脚本。Pyparsing还允许你轻松地定义在Python上下文中运行的定制脚本语言。Python实现的系统旨在能够独立执行用户传递的一系列命令。你希望系统以脚本的形式接收命令。用户应该能够定义条件。这种对通信中逻辑元素的最初简单的声音要求&am…

【Hello Linux】初识操作系统

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍下操作系统的概念 操作系统 操作系统是什么&#xff1f; 操作系统是管理软硬件资源的软件 为什么要设计操作系统 为什么要设…

认识html

1.html的特点先看一段简单的html代码<html><head></head><body>hello world</body> </html>如果将这段带有这段代码的.html文件拉进浏览器中,就会出现一个页面,内容就是hello world,如下图:由上面的代码,我们可以了解到一些html代码的特点…

Java - 数据结构,队列

一、什么是队列 普通队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(FirstIn First Out) 入队列&#xff1a;进行插入操作的一端称为队尾&#xff08;Tail/Rear&#xff09; 出队列&#xf…

【华为OD机试模拟题】用 C++ 实现 - 对称美学(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 获得完美走位(2023.Q1) 文章目录 最近更新的博客使用说明对称美学题目输入输出示例一输入输出说明示例二输入输出说明备注Code使用说明 参加华为od机试,一定要注意不要完全背诵代码࿰

五、DeepWalk、Node2Vec论文精读与代码实战【CS224W】(Datawhale组队学习)

开源内容&#xff1a;https://github.com/TommyZihao/zihao_course/tree/main/CS224W 子豪兄B 站视频&#xff1a;https://space.bilibili.com/1900783/channel/collectiondetail?sid915098 斯坦福官方课程主页&#xff1a;https://web.stanford.edu/class/cs224w 文章目录D…

拿下域控后,我还是对大佬的操作念念不忘

历来攻防演练中&#xff0c;我都笃信一个道理——吃饱了才有力气干活。所以&#xff0c;在清晨的客户现场&#xff0c;当看到大佬满意地吃完了我带来的煎饺&#xff0c;我知道这一战&#xff0c;我们作为攻击队&#xff0c;基本已经拿下了。 虽然说的每一句话都带着一股醋味儿…

Android 高工分享一波性能优化的总结~

随着 Android 开发越来越规范&#xff0c;国内工程师的素质&#xff0c;以及用户对产品的要求也越来越高。这也间接导致我们对研发项目的质量要求到了近乎苛刻的地步&#xff0c;**内存优化、UI 卡顿优化、App 崩溃监控等性能调优也逐渐成了人手必备的技能。**工作之余&#xf…

Boost资料整理备忘

Boost资料整理备忘 网络资源 书籍: The Boost C Libraries官方文档 Boost Library Documentation random boost.randomBoost随机库的简单使用&#xff1a;Boost.Random(STL通用)tutorialstd::random boost::asio Boost.Asio 网络编程 - 基本原理Boost.Asio DocBoost定时器 网…

理光M2701复印机载体初始化方法

理光M2701基本参数&#xff1a; 产品类型&#xff1a;数码复合机 颜色类型&#xff1a;黑白 复印速度&#xff1a;单面&#xff1a;27cpm 双面&#xff1a;16cpm 涵盖功能&#xff1a;复印、打印、扫描 网络功能&#xff1a;支持无线、有线网络打印 接口类型&#xff1a;USB2.0…

如何建立项目标准化评价体系?【锦狸】

PMO团队面临着管理多个项目&#xff0c;甚至是多个项目集&#xff0c;多个产品集的问题&#xff0c;那么如何对项目们进行标准化评价体系的建设&#xff0c;就是PMO需要首先思考的问题。 首先我们要关注项目的背景&#xff0c;了解了项目背景之后&#xff0c;我们才可以明确项…

CPython解释器性能分析与优化

原文来自微信公众号“编程语言Lab”&#xff1a;CPython 解释器性能分析与优化 搜索关注 “编程语言Lab”公众号&#xff08;HW-PLLab&#xff09;获取更多技术内容&#xff01; 欢迎加入 编程语言社区 SIG-元编程 参与交流讨论&#xff08;加入方式&#xff1a;添加文末小助手…

【Linux】使用U盘自动化安装Linux(VMware虚拟机)

文章目录前言一、准备二、新建虚拟机2.1 创建虚拟机2.2 新增硬盘2.3 系统启动项三、加电运行四、EFI方式五、总结前言 一、准备 基于之前的基础【Linux】Kickstart 配置U盘自动化安装Linux系统&#xff0c;现在我们可以在虚拟机中尝试自动化安装Linux系统。 二、新建虚拟机 …

POI导入导出、EasyExcel批量导入和分页导出

文件导入导出POI、EasyExcel POI&#xff1a;消耗内存非常大&#xff0c;在线上发生过堆内存溢出OOM&#xff1b;在导出大数据量的记录的时候也会造成堆溢出甚至宕机&#xff0c;如果导入导出数据量小的话还是考虑的&#xff0c;下面简单介绍POI怎么使用 POI导入 首先拿到文…

Java:如何选择一个Java API框架

Java编程语言是一种高级的、面向对象的语言&#xff0c;它使开发人员能够创建健壮的、可重用的代码。Java以其可移植性和平台独立性而闻名&#xff0c;这意味着Java代码可以在任何支持Java运行时环境(JRE)的系统上运行。Java和Node js一样&#xff0c;是一种功能强大的通用编程…

机试指南

文章目录零、绪论和IDE安装int取值范围常犯的编程小错误一、枚举和模拟 (暴力求解)(一) 枚举1.Reverse函数 求 反序数2.程序出错的原因1.编译错误 (compile)&#xff1a;基本语法错误2.链接错误 (link)&#xff1a;函数名写错了3.运行错误 (run)&#xff1a;结果与预期不符&…

前后端分离开发Springboot+VUE学习笔记

学习内容来源&#xff1a;传送门 目录前后端分离实现技术创建vue项目在idea中打开新建页面创建SpringBoot应用创建实体对象与数据库表元素绑定创建实体类接口前端调用数据跨域传输在springboot中解决总结前后端分离 前后端分离就是将一个应用的前端和后端代码分开写&#xff0…

前端:分享JS中7个高频的工具函数

目录 ◆1、将数字转换为货币 ◆2、将 HTML 字符串转换为 DOM 对象 ◆3、防抖 ◆4、日期验证 ◆5、将 FormData&#xff08;表单数据&#xff09;转换为 JSON ◆6、衡量一个函数的性能 ◆7、从数组中删除重复项 JavaScript 实用函数是有用的、可重复使用的片段&#xff0…

STM32开发(14)----CubeMX配置ADC

CubeMX配置ADC前言一、什么是ADC&#xff1f;二、实验过程1.单通道ADC采集STM32CubeMX配置代码实现2.多通道ADC采样(非DMA)STM32CubeMX配置代码实现3.多通道ADC采样&#xff08;DMA&#xff09;STM32CubeMX配置代码实现总结前言 本章介绍使用STM32CubeMX对ADC进行配置的方法&a…