【linux】:进程状态(僵尸进程等)以及环境变量(下)

简介: 【linux】:进程状态(僵尸进程等)以及环境变量(下)

二、环境变量



环境变量一般是指操作系统中用来指定操作系统运行环境的一些参数,比如我们在编写c/c++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找,环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。比如我们在linux中写的可执行程序,要想这个程序先运行起来必须在前面就是 .   /   ,  . 是在当前路径,/ 是路径分隔符,而同样为可执行程序的 ls指令等却不需要在前面加上./,难道就因为一个是被纳入系统的程序一个是我们自己写的吗?其实并不是这样,系统的指令之所以不需要在前面加./是因为有环境变量的帮助,这个环境变量会帮我们去搜索系统中的ls命令,而这个环境变量叫PATH,下面我们查看一下这个环境变量:

eef2400857064d3984f83907a6e6973a.png

echo是打印一个字符串,PATH是环境变量,前面加上$符号就是获取环境变量的内容,这里与指针解引用相似。


和环境变量相关的命令:


1.echo:显示某个环境变量值


2.export:设置一个新的环境变量


3.env:显示所有环境变量


4.unset:清除环境变量


5.set:显示本地定义的shell变量和环境变量

fa6597d954d5457a9cbf4f001828b532.png

我们之前讲过linux的指令,which可以查看指令的路径,通过查看我们发现ls指令在usr/bin中,而PATH环境变量是根据冒号一个一个路径进行查找,当找到usr/bin这个路径的时候就不需要我们在使用的时候加./了。那么如何将我们写的可执行程序添加到环境变量中呢?看下图:

db99d84aed4d48f88c3223e9c1526bbf.png

我们写了一个程序用来演示。接下来我们用命令将我们写的这个程序加入到环境变量中


9179e0db8aa74d2196d602781ee889d4.png


可以看到我们成功添加,然后我们试试可以直接运行吗?

c3f9e490a15a4b9593cea23c8f8b8584.png


我们看到是可以运行的并且不用在输入前面的./了

827ead7ebe764ca78c953512cf28bc88.png

这个时候我们的其他指令不能使用该怎么办呢?这时只需要重新登录xshell即可。

那么我们怎么样才能既使用系统的指令又用自己的呢?

69c775a1039445efa5443b330d36f084.png

我们将刚刚的命令修改一下就可以既使用系统的指令又用自己的。当然除了这一种方式我们还可以直接将要添加的可执行程序的目录拷贝到PATH中,而这种方式在linux中相当于软件的安装。

下面我们用env指令查看系统中的环境变量:

d4dbfd76edcf4344be89b8c9c2551257.png


我们可以看到系统中的环境变量很多,当然我们也可以用history指令查看以往我们用过的指令:

10c64bfd8c7d49a7880dd3db7da4d4da.png


为什么从10开始呢,因为history只会保留最新的1000条指令,一旦超过就会删掉原来旧的指令。

下面我们用C语言来获取系统中的环境变量:

1053a65ec3f145e0ac903e548dfecbb6.png

我们再写c/c++的时候从来没有写过main函数的参数,而main函数实际上有3个参数,这三个参数不需要我们手动去写编译器会默认给我们传参,envp这个指针数组中每一个指针都指向一个有效的字符串,而最后一个指针必须以NULL结尾。

437592c9d81447f69511ffb70f3eb002.png


然后我们将代码写完整如下图:

517d42ddc8ed4c258f8552a19429ef7a.png

为什么for循环中envp没有写判断呢?因为我们刚刚说过,envp这个指针数组中最后一个指针指向的一定是NULL,而NULL在for循环中对应为假,所以不需要写判断语句。

91984d5470944dd896117db9c15d9955.png

由于使用main函数的三个参数是c99标准下的,所以我们在编译后面加上c99。0493d41210ec4fc88805e0a966a6dec6.png

然后我们直接运行程序发现这里的环境变量与我们用env命令显示的一致。


总结:环境变量本质就是内存级的一张表,这张表由用户在登录系统的时候,进行给特定用户形成属于自己的环境变量表。环境变量中的每一个都有自己的用途,有的是进行路径查找的,有的是进行身份认证的,有的是进行动态库查找的,有的是用来进行确认当前路径等等,每一个环境变量都有自己特定的应用场景。那么环境变量对应的数据都是从哪来的呢?是从系统的相关配置文件中读取进来的。下面我们验证一下:


我们先用ctrl + ~进入家目录,然后输入指令ls -al查找文件:

e0a14d674ac247ba9d4c4c1b727fb701.png

我们可以看到bash的两个shell脚本,然后我们用vim打开这个脚本:

ae34742d84d447578034c3d119f5a4f0.png

我们用vim进入etc/bashrc,注意在etc目录下bashrc是全局的。

5463d7bebacc4306bfd430955fc36dfb.png

比如我们命令行上的# 或者 $提示符就是这样编写的。  环境变量是通常具有全局属性的,当我们写了一个环境变量val=100,然后这个环境变量就会shell的表中,当我们给这个进程在开一个子进程的时候,shell中的这张表也会交给子进程,这样子进程中也就有了环境变量val=100,下面我们来证明一下:

946aac7ad9fc4dce8ad5b3cdc71bf470.png

我们先自己导入一个环境变量,然后输入env命令查看:

97d7963b289b40c0badbd1e5bb70f892.png


我们看到确实将这个环境变量添加到系统中,下面我们修改一下代码进行演示:

17dd266e3a7b436f9bee421adfb364cc.png


getenv()函数是获取一个环境变量并打印

02d0eb73320c493e99461da6c3318923.png

我们从上图中可以看到成功获取到了我们自己设的环境变量,我们前面讲过当我们运行一个进程的时候这个进程的父进程是bash,刚刚我们的环境变量是保存在系统中也就是说只有bash可以访问,但是现在这个子进程也可以使用就说明了环境变量是全局的,会由父进程传给子进程。

d9aed7534c1c46f2a3093c444c92f572.png

我们定义了一个变量前面没有加export,然后我们在前面加$符号打印其内容发现也能正常打印

721859772cf748c09ecbc161b9eacd02.png

下面我们用getenv获取一下这个环境变量:

a815b9ad3e4d4774a0e5ddc509c16cff.png3886220543ad459d90366fcce00653ea.png

这个时候我们发现用函数获取环境变量获取不到我们刚刚定义的hello1,也就是说不带export定义的环境变量是不可以被getenv()获取到的,那么也就不可以被子进程继承,那么为什么加了export就能被继承呢?因为不加export定义的环境变量是不会被添加到环境变量表中,这样的变量被称为shell的本地变量,这种变量只能在shell内部有效。

b01629f725ca4cdba22c8b2362c99dd0.png 因为hello1已经在shell本地了,所以前面加export可以直接将hello1添加到环境变量表,也就可以正常被子进程继承了。

接下来我们继续解释刚刚main函数的三个参数中的另外两个。

6919d0e5236a4f24b8c0fd25e610f666.png


argv的使用与argc都有一个共同点,就是不需要在判断结束条件。

6e4188fc28384bdb91e521796a593cc6.png

如下图所示:

f97e681055f84c0492bef8c8f721e5be.png


-a -b其实是参数选项,my2.24是可执行。那么这个操作有什么作用呢?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
//int main()
//{
//  int cnt = 10;
//  while (cnt--)
//  {
//    printf("这里在倒计时:%d\n",cnt);
//  }
//  return 0;
//}
void Usage(const char* name)
{
  printf("\nUsage:%s -[a|b|c]\n",name);
  exit(0);
}
int main(int argc,char* argv[])
{
  if (argc!=2) Usage(argv[0]);
  if (strcmp(argv[1],"-a")==0) printf("打印当前目录下的文件名\n");
  else if(strcmp(argv[1],"-b")==0) printf("打印当前目录下的详细信息\n");
  else if(strcmp(argv[1],"-c")==0) printf("打印当前目录下的文件名(包含隐藏文件)\n");
  else printf("其他功能,待开发\n");
//{
//  for (int i = 0;argv[i];i++)
//  {
//    printf("argv[%d]->%s\n",i,argv[i]);
//  }
  return 0;
}
//int main()
//{
//  printf("myenv:%s\n",getenv("hello1"));
//  return 0;
//}

我们重新写一段代码,然后我们运行起来。


b4680554930146ad93724193fd4aab62.png

启动软件后这个软件告诉我们使用方法是./my2.24 + abc任意一个字符

6ad89f683c6240bdbbe80480f81ad57f.png


这样就能完成一个类似于打印目录的操作,这只是简单的演示实际上可以实现一些有用的东西。


总结



本篇文章相较于上一篇进程的概念多了很多需要实践的东西,比如测试进程的优先级,理解孤儿进程,学会理解环境变量并且可以自己添加环境变量,环境变量的获取,环境变量的修改等。下一篇继续更深入的学习linux的进程,即使进程这部分概念多也希望大家可以多多练习才能更深入的理解进程。

目录
相关文章
|
11月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
373 67
|
10月前
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
284 16
|
10月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
201 20
|
9月前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
214 0
|
9月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
285 0
|
9月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
168 0
|
9月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
230 0
|
6月前
|
Linux 应用服务中间件 Shell
二、Linux文本处理与文件操作核心命令
熟悉了Linux的基本“行走”后,就该拿起真正的“工具”干活了。用grep这个“放大镜”在文件里搜索内容,用find这个“探测器”在系统中寻找文件,再用tar把东西打包带走。最关键的是要学会使用管道符|,它像一条流水线,能把这些命令串联起来,让简单工具组合出强大的功能,比如 ps -ef | grep 'nginx' 就能快速找出nginx进程。
735 1
二、Linux文本处理与文件操作核心命令
|
6月前
|
Linux
linux命令—stat
`stat` 是 Linux 系统中用于查看文件或文件系统详细状态信息的命令。相比 `ls -l`,它提供更全面的信息,包括文件大小、权限、所有者、时间戳(最后访问、修改、状态变更时间)、inode 号、设备信息等。其常用选项包括 `-f` 查看文件系统状态、`-t` 以简洁格式输出、`-L` 跟踪符号链接,以及 `-c` 或 `--format` 自定义输出格式。通过这些选项,用户可以灵活获取所需信息,适用于系统调试、权限检查、磁盘管理等场景。
435 137
|
6月前
|
安全 Ubuntu Unix
一、初识 Linux 与基本命令
玩转Linux命令行,就像探索一座新城市。首先要熟悉它的“地图”,也就是/根目录下/etc(放配置)、/home(住家)这些核心区域。然后掌握几个“生存口令”:用ls看周围,cd去别处,mkdir建新房,cp/mv搬东西,再用cat或tail看文件内容。最后,别忘了随时按Tab键,它能帮你自动补全命令和路径,是提高效率的第一神器。
1139 58