小编是双非本科大一菜鸟不赘述,欢迎大佬指点江山(企鹅:1319365055)
此前博客点我!点我!请搜索博主 【知晓天空之蓝】
非科班转码社区诚邀您入驻
小伙伴们,打码路上一路向北,彼岸之前皆是疾苦
一个人的单打独斗不如一群人的砥砺前行
这是我和梦想合伙人组建的社区,诚邀各位有志之士的加入!!
直达: 社区链接点我
倾力打造转码社区微信公众号
系统中进程的数据是极多的,而 CPU 只有少量,因此进程之间会存在竞争性。为了高效的完成任务更合理的竞争相关资源,就具有了优先级。虽然是多线程运行,但是需要独享各种资源,多线程期间是互不干扰的,也就是独立性。
于是乎就引出了两个概念:并行和并发。
如果存在多个 CPU,在任何一个时刻,都有可能两个进程在同时运行,这就是并行。但是如果我电脑是单 CPU,他也能维持多个进程同时运行,是如何做到的呢?
然而我们绝大部分的操作系统都是分时的,操作系统会给到每一个进程,在一次调度周期中,赋予了一个时间片的概念。比如此时有 3 个进程,但是我只给每个进程 10 ms 的时间,然后操作系统将进程一剥离再赋予进程二同样的时间。也就是说在一个时间段内,多进程会通过交叉切换的方式得到推进,这就叫做并发。
我们说过操作系统就是简单的感觉队列来进行先后调度,那如果突然来了一个优先级更高的进程呢?其实现在的计算机都支持的是抢占式内核,即优先级更高的进程会抢占 CPU 资源,CPU 会将当前进程剥离来先执行此进程。
Linux 会根据不同的优先级,将特定的进程放入不同的队列中,因此相同优先级的进程是可以存在多个的。而不同的队列最终组成 CPU 里的一个运行队列 task_struct *queue,他就是一个简单的哈希表结构,其中操作系统会用 swap 函数交换新老进程进行迭代。
struct runqueue
{
hash queue *active;// 活跃进程
hash queue *old;//过期进程
}
哈希表中每个成员的下标是各自的优先级大小,存放在该表相对位置,扫描该表时查找到优先级最高的开始调度,这就是分段式的管理。
CPU 内的寄存器可以进行临时的数据存储,寄存器非常少但是十分重要。
寄存器又分为可见寄存器和不可见寄存器,就好像函数体内部的临时变量如何 return 之后来影响其他变量,我们老早就说过了,这个临时变量早就被释放了,但是他的值会被写入 eax 寄存器来充当返回值。这个例子里的这种通用寄存器,能直接使用的就是可见寄存器,而有些操作系统的权限寄存器和状态寄存器就是不可见寄存器。
所谓切换就是切出原来的再放进新的?NO,进程间切换并没有想象的那么简单,操作系统把原来的进程切走,我不能直接卷铺盖就走人,还应该把 CPU 内的临时数据保存好,为了数据的恢复。我们把进程运行中的各种寄存器数据,我们叫做进程的上下文数据,在进程恢复时需要将保存的上下文数据恢复到寄存器
那么上下文的数据保存在哪里呢?我们之前讲 PCB 时,其实 task_struct 里面就有一个字段是用来保存上下文数据的。
有个问题,在 Linux 中那么多指令,touch,ls,make 他们好像都是可以直接执行,也可以带路径执行,但是我们自己写的代码或者指令却只能以 ./ 带路径的方式才能执行呢?
我们要实习一个程序,首先就需要先找到他,那么问题实质就改变了:系统为什么能找到他的命令我们的代码却找不到?这就引出了一个新的概念:环境变量
命令行变量就分为两种:普通变量和环境变量(全局),环境变量保存了程序相关的搜索路径,系统中的环境变量名叫 PATH,我们在 Linux 上可以通过 env 指令查看所有环境变量,那么 PATH 也是可以查出来的:
也可以 echo 指令查看 PATH 内容:
要想把我们自己的指令直接执行其实就很简单了,直接 copy 到这里的 /usr/bin/ 目录下,有了系统路径就可以直接执行了:
sudo cp myproc /usr/bin/
如何定义环境变量呢?很简单,在定义普通变量基础上加上 export 指令:
然后导入到 PATH 的路径里面即可:
export PATH = $PATH:……
要取消环境变量就直接 unset 即可:
unset name
PATH: 指定命令的搜索路径
HOME: 指定用户的主工作目录,即登录到 Linux 时的默认目录
SHELL: 当前 shell ,通值就是 /usr/bash
mian 函数可以带参数吗?如果能带那么能带几个?
之前我们说可以带且能带两个,main 函数中 argc 和 char *argv[] ,命令行传递的是命令行中输入的程序名和选项,他俩组合起来就是 char *argv[argc]。
但是其实 main 函数可以带最多三个参数,第三个神秘人就是== char* env[]==,他就是环境变量,他也是指针数组,每个程序会收到一个环境表,他就是这个指针数组,每个指针指向一个 ‘\0’ 结尾的环境字符串
但是很多时候我们并没有去传这仨参数,他们是怎么传的呢?那么请思考一下:无参函数能进行显式传参吗?其实一个无参函数强制带参是不会报错的,甚至还能正常编译,只要不把参数搞成 void 就行。这说明了进程获取环境变量方法之一就是依靠 mian 函数传达。
还有一个方法就是 C 语言会给我们自己定义一个全局变量 **environ,他里面包含了当前所有的环境变量:
extern char** environ;
for(int i = 0;envrion[i];i++)
{
printf("%d:%s\n",i,envrion[i]);
}
当然我们如果想获取特定的环境变量,可以通过一个接口 getenv() 直接获取指定的环境变量:
char *val = getenv("PATH");
printf("%s\n",val);
我们为什么要搞环境变量啊?
其实搞环境变量的目的就是为了以防万一,我要是想要一个程序只能我自己运行,就可以对 USER 变量动动手脚,切换后即使 root 权限都没有办法运行,其实这就是图个玩儿,其实在系统中也是通过环境变量的限制来得知用户的某些权限操作。
aqa 芭蕾 eqe 亏内,代表着开心代表着快乐,ok 了家人们。