目录
☃️1.奇奇怪怪的现象和孤儿进程
首先回顾一下之前我们学过的fork()创建子进程
fork(void)的返回值有两种
注意fork()头文件是
运行一下代码
结果是
看起来没什么问题
下面我们定义一个全局变量gal,并且只在子进程修改gal的值
结果是
我们发现不对啊,明明在子进程我们都把全局变量修改过,但是看起来好像父进程的值依然不变,但是两个相同的值居然有一样的地址
为了解释这个现象,我们看一段代码
创建子进程之后一段时间让父进程直接退出
发现子进程的ppid=1,也就是父进程退出之后子进程被一号进程(os)领养
我们把被领养的进程叫做孤儿进程
为什么父进程退出之后这个进程一定要被领养?
因为一个进程没人领养它,他就会一直处于僵尸状态,没人回收他
并且孤儿进程直接ctrl c杀不死,必须killall 进程名
☃️2.环境变量
为什么每次运行程序的时候要./ 但是Linux下一切皆文件,ls这样简答的一条语句也是用程序写出来的,但是在执行命令的时候我们就直接ls?
因为系统里有环境变量
用echo $PATH 指令查看环境变量列表,该列表是以:为分割的若干子路径
而找一下ls所在文件路径(which ls)
有没有发现!!!
所以很好解释上面的问题,因为ls命令所在路径(文件列表)在环境变量列表的路径中,而直接执行一个程序的前提是在环境变量的列表从左到右挨个子路径找到他,找不到就不能直接执行
如果我想把自己的进程路径添加到这个列表里
所以我们好像发现可以解释很多的Linux现象
在Linux中把可执行程序拷贝到系统默认的路径下让我们可以直接访问的方式 相当于Linux下的软件安装!!!!
此时直接运行程序不加./完全没问题
刚在用的指令查看了环境变量的路径
同样的指令还可以加上不同的环境变量
下面的指令用来记录当前正在使用Linux的用户是谁
所以很好解决了之前说的 权限问题,为什么OS知道谁是普通用户谁是root
是这个USER的环境变量帮我们保存着用户姓名
那么如何查看其余的环境变量?
指令env
其中的HISTSIZE=3000
用history指令查看历史指令
如果指令数量达到3000,那么OS会把最早的代码清理掉一条,方便存储新来的一条指令,一次下去保存最近的3000条指令
echo $HOME 保存当前登录用户的家目录
☃️3.深刻理解main函数参数和命令行参数
你知道main函数有参数吗??
没错这三个参数我们都会逐一讲解
这个代码需要C99标准执行,并且从今往后我们再也不用像之前一样写目标文件和依赖文件名称
红框内容完全可以被下面的代码代替,其实$@就是目标文件的符号表示 $^就是依赖文件的符号表示
首先打印一下这个char* envp[],在C语言,我们知道这是一个指针数组,数组里面存放的指针
不管里面有多少有效数据吗,假设有40个,那么第41个就指向NULL
并且打印地址发现这里面的内容不就是刚才env查看到的环境变量吗!!!!
所以envp其实是一个表结构,是传递给进程的环境变量表
你以为你从来写代码没有接触环境变量,其实无时无刻不在使用!!!!!!
但是上面获取环境变量的打印方式太挫了
最主流的还是函数获取
char *getenv("环境变量名称"); 获取失败返回NULL
他的头文件是#include <stdlib.h>
那么那么,用函数获取环境变量是不是意味着我们可以自己实现一个指令!!!!!
我们来自己实现一个pwd指令
运行一下 发现没什么问题
把可执行程序的名字改成我自己的pwd
然后按照前面说过的添加我的可执行程序到环境变量的列表中
惊喜发现我们写了一条自己的指令,并且完全正确
当然我们也可以通过这个函数写一个系统墙相关的代码
这个代码就是只能wrt用户和root执行,否则不可以
现在我把NAME改成“wr” 结果如下
结论:
1.环境变量就是内存级的一张表,这张表由用户在登录系统的时候进行给特定用户形成属于自己的环境变量表
之所以说他是内存级的表,是因为内存的数据在没被加载到内存之前,环境变量都是从系统的相关配置文件中读取来的,环境变量在shell内部维持
2.每一个 环境变量都有自己的用途,自己的特定应用场景
下面对main函数 其他参数解释
其实每个元素都是kv的,即,有自己的名字和内容
这样把hello添加到环境变量中 env可以查到
但是
这样一个简单的变量没有export,就不能被env找到
其实他的原理是这样的
刚才的hi相当于非环境变量,不在表里
但是hello在环境变量表里
当我们export hello='1122' 相当于shell在其内部找到一块空间(没被占用的)
让这块空间的chao*不指向NULL了,改为指向hello的字符串
如果空间不够了还会malloc一块内存
shell启动的时候,是从系统的配置文件中读取环境变量表然后初始化这张表
并且环境变量表可以被子进程继承下去——环境变量有全局属性
刚才的hi叫本地变量,只在shell内部有效,不可以被子进程继承
如果想让他变成环境变量,直接
不需要
这次可以env找到
所以export的工作就是把本地的变量添加到环境变量表里
现在看
其实argv也是一张表,他的类型和envp一样
那么我们来看一下他是干什么的
好奇怪,好像我们输入什么选项他就把选项添加到自己的argv表里面了
所以命令行参数就是这整个字符串
argc表示的就是命令行参数的个数 argv就是命令行参数对应的多个子串起始地址的一张表
那么命令行参数的意义就是下面的代码
结果:
也就是实现 -x 选项功能!!!!