一:孤儿进程
在Linux系统中,当一个进程创建了子进程后,如果父进程执行完毕或者提前退出而子进程还在运行,那么子进程就会成为孤儿进程。子进程就会被systemd(系统)进程收养,其pid为1
myprocess.c代码
1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 5 int main()6 {7 pid_t id = fork();8 if(id == 0)9 {10 //child11 while(1)12 {13 printf("我是一个子进程,我的pid:%d,ppid:%d\n",getpid(),getppid());14 sleep(1);15 }16 }17 18 else19 {20 //parent21 int cnt = 3;22 while(cnt)23 {24 printf("我是一个父进程,我的pid:%d,ppid:%d\n",getpid(),getppid());25 cnt--;26 sleep(1);27 }28 }29 30 return 0;31 }
如上面myprocess.c代码所示,子进程会一直执行,而父进程执行三次之后就会退出,因此子进程就会成为孤儿进程,子进程就会变成后台进程 ,如下图所示
孤儿进程要想杀掉,不能使用Ctrl + C,只能同时打开两个XShell通过kill -9 + pid
二:进程优先级
2.1 优先级
2.1.1 含义:
进程得到CPU资源的先后顺序就是进程优先级
2.1.2 意义:
目标资源稀缺是,导致进程要通过优先级确认谁先谁后的问题
2.1.3 规则:
原则上来说,优先级也是一个数字,数值越小,优先级越高;反之数值越大优先级越低
优先级数值范围为[60,99]共40个优先级
2.2 优先级查看
命令:
ps -al | head -1 && ps -al | grep myprocess
执行该命令后,首先会显示进程信息的标题行,接着显示所有名称包含 myprocess 的进程详细信息。
myprocess.c代码
1 #include<stdio.h>2 #include<unistd.h>3 #include<sys/types.h>4 5 6 int main()7 {8 pid_t id = fork();9 if(id == 0)10 {11 //child12 while(1)13 {14 printf("我是一个子进程,我的pid:%d,ppid:%d\n",getpid(),getppid());15 sleep(1);16 }17 }18 19 else20 {21 //parent22 while(1)23 {24 printf("我是一个父进程,我的pid:%d,ppid:%d\n",getpid(),getppid());25 sleep(1);26 } 27 } 28 return 0;29 }
如上图所示,执行该命令后,打印出了myprocess代码中的进程信息,其中PRI是进程的优先级,默认值为80;NI是进程优先级的修正数据,也称为nice值。进程的真实优先级 就为默认PRI 和 NI两者的和。所以myprocess的进程优先级为默认PRI(80) + NI(0) = 80
2.3 top修改优先级
同时打开两个XShell,一个开始运行代码,另一个输入top命令,,然后输入r,按照提示输入需要修改优先级的进程pid来重新调整优先级,然后输入数字表示想要将进程的NI值修改成多少,然后按Ctrl+ c退出即可
如上图所示,原本进程的PRI为80,NI为0,我们使用top命令修改NI值为10之后,进程的PRI变为90,NI变为10,那么进程优先级90是怎么得来的,即默认PRI(80) + NI(10) = 90
2.4 renice修改进程优先级
在Linux中,renice命令用于修改已经运行进程的优先级,也就是调整进程的NI值
基本语法:
renice 设置nice数值 -p 进程ID(PID)
- nice值的范围为-19 ~ 20
- -p 用于指定进程ID
如上图所示,执行renice -100 -p 1938344该命令后,系统会尝试将进程ID为1938344的进程的nice值设置为-100。从上图我们可以看到,我们明明是将nice值设置为-100了,为什么打印出来的是
-20呢。这是因为nice值的最低取值范围为-20,而我们使用renice 100 -p 1938344命令将进程ID为1938344的进程的nice值设置为100时,最后的nice值却为19,所以nice值的最高取值范围为19
有上面可知,进程优先级的取值范围为[80 + (-20),80 + 19]即,[60,99]
三:环境变量
在Linux系统中,环境变量是一种具有特定名称的对象,其作用是存储系统运行环境的相关信息。这些信息能够被运行在系统上的进程所使用,为系统和应用程序的运行提供必要的配置和参数。
3.1 前导知识
我们知道如果我们执行系统命令不用加上路径就可以执行,而我们执行自己的命令如果不加上路径就会报错。但是系统命令和我们自己写的命令两者没有本质区别,而且要执行一个程序我们必须先找到它,而系统命令由于存在环境变量来帮助系统找到目标文件
code.c代码:
1 #include<stdio.h>2 #include<string.h>3 4 int main(int argc,char* argv[])5 { 6 if(argc != 2)7 { 8 printf("Usage:%s [-a|-b|-c]\n",argv[0]);9 return 1;10 }11 12 const char* arg = argv[1];13 14 if(strcmp(arg,"-a")==0)15 printf("这是功能1\n");16 else if(strcmp(arg,"-b")==0)17 printf("这是功能2\n");18 else if(strcmp(arg,"-c")==0)19 printf("这是功能3\n");20 else21 printf("Usage:%s [-a|-b|-c]\n",argv[0]);22 return 0;23 }
如上图所示:实行./code -a/-b命令系统就能正常执行,但是实行code -a就不行,这是因为code.c是我们自己写的程序代码,要加上路径才能执行,./code -a就代表在当前路径下寻找code这个可执行文件,而不带./就默认在系统环境变量中寻找,没有找到就报错了
3.2 环境变量PATH
这个变量保存了可执行文件的搜索路径,系统在查找可执行文件时,会按照PATH中指定的路径依次进行搜索
echo $PATH
如上图所示,我们使用echo $PATH命令后,系统就会将所有的环境变量PATH下的绝对路径,每一个路径之间以冒号(:)分割。因此我们输入一个命令后系统就会默认在环境变量PATH下的路径进行一一搜索,如果没有找到就会报command not found
在上面我们提到如果命令能在系统中存在我们就可以不用带路径执行该命令,而环境变量PATH就记录着系统的环境变量的路径,因此只要在环境变量PATH记录的路径上加上我们想要执行的命令的路径是否就意味着我们也可以不带路径执行该命令呢?是的,添加方法如下:
往PATH上添加路径方法:
PATH=$PATH:想要添加的路径
如上图所示:我们想在PATH变量加上当前路径/home/cwy/cw/linux/lesson13,使用PATH=$PATH:/home/cwy/cw/linux/lesson13命令后我们可以看到环境变量PATH已经加上/home/cwy/cw/linux/lesson13了,执行code -a 也没有报错
微提示:这种方法只是临时的,如果我们将XShell关掉重新启动之后,PATH就会变成之前的
3.3 env查看所有的环境变量
如上图所示,输入env命令后,系统就会将所有的环境变量打印出来
3.4 环境变量HOME
该变量指向用户的家目录,也就是用户登录系统后默认进入的目录
echo $HOME
3.5 export环境变量设置
如我们想在环境变量中新增一个环境变量MYENV,使用export MYENV=11223344命令后就将MYENV变量添加成功
3.6 unset取消环境变量
如我们想在环境变量中删除环境变量MYENV,使用unset MYENV命令后就将MYENV变量删除成功
3.7 获取环境变量
3.7.1 方法一:main函数参数法
code.c代码:
1 #include<stdio.h>2 #include<string.h>3 4 int main(int argc,char* argv[],char* env[])5 {6 for(int i = 0;env[i];i++)7 {8 printf("env[%d]-> %s\n",i,env[i]);9 } 10 return 0;11 }
如上图所示:在code.c代码中,我们可以看到main函数参数中有一个字符串数组char* env[],该数组用于存储环境变量,每个元素是一个形如变量名=变量值的字符串,数组以NULL结尾;使用for循环变量env数组,只要env[i]不为NULL就打印当前环境变量的索引和值,如下图所示:
3.7.2 方法二:系统函数getenv()
在Linux系统里,getenv是一个用于获取环境变量值的函数
函数定义
#include<stdlib.h>
char* getenv(const char* name);
- 参数:name是一个执行以空字符结尾的字符串指针,代表要获取的环境变量的名称
- 返回值:若环境变量存在,函数会返回该环境变量值的指针;若环境变量不存在,则返回NULL
code.c代码
1 #include<stdio.h>2 #include<string.h>3 #include<stdlib.h>4 5 int main(int argc,char* argv[],char* env[])6 { 7 8 char* value = getenv("PATH");9 if(value == NULL)10 return 1;11 printf("PATH->%s\n",value);12 return 0;13 }
如上图所示:我们通过getenv函数来获取PATH环境变量的值,如果PATH不存在为NULL则返回1;反之打印环境变量PATH的内容,如下图所示:
3.7.3 方法三:environ全局变量
在Linux环境里,environ是一个全局变量,能让我们访问进程的环境变量
函数定义:
environ是一个全局变量,定义在<unistd.h>头文件中,其本质是一个字符串指针数组,数组中的每个元素指向一个形如变量名=变量值的字符串,数组以NULL结尾
extern char** environ;
code.c代码:
1 #include<stdio.h>2 #include<string.h>3 #include<stdlib.h>4 #include<unistd.h>5 6 extern char** environ;7 8 int main(int argc,char* argv[],char* env[])9 { 10 11 for(int i = 0;environ[i];i++)12 { 13 printf("environ[%d]-> %s\n",i,environ[i]);14 }15 return 0;16 }
3.8 本地变量
格式:变量=值,等号两边不能带空格
如上图所示:使用i=10,定义了一个值为10 的本地变量并使用echo打印搬到变量i的值
3.9 set显示所有变量
使用set命令可以显示当前XShell的所有变量,包括环境变量,本地变量等