linux系统编程学习_(1)进程相关概念、多道程序设计概念、CPU与MMU、进程控制块(PCB)及环境变量
进程相关概念
程序和进程
程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu、内存、打开的文件、设备、锁…) 进程,是一个抽象的概念,与操作系统原理联系紧密。进程是活跃的程序,占用系统资源。在内存中执行。(程序运行起来,产生一个进程) 程序 → 剧本(纸) 进程 → 戏(舞台、演员、灯光、道具…) 同一个剧本可以在多个舞台同时上演。同样,同一个程序也可以加载为不同的进程(彼此之间互不影响) 如:同时开两个终端。各自都有一个bash但彼此ID不同。
并发
并发,在操作系统中,一个时间段中有多个进程都处于已启动运行到运行完毕之间的状态。但,任一个时刻点上仍只有一个进程在运行。
多道程序设计
在计算机内存中同时存放几道相互独立的程序,它们在管理程序控制之下,相互穿插的运行。多道程序设计必须有硬件基础作为保证。 时钟中断即为多道程序设计模型的理论基础。 并发时,任意进程在执行期间都不希望放弃cpu。因此系统需要一种强制让进程让出cpu资源的手段。
时钟中断有硬件基础作为保障,对进程而言不可抗拒。 操作系统中的中断处理函数,来负责调度程序执行。
在多道程序设计模型中,多个进程轮流使用CPU (分时复用CPU资源)。而当下常见CPU为纳秒级,1秒可以执行大约10亿条指令。由于人眼的反应速度是毫秒级,所以看似同时在运行。
实质上,并发是宏观并行,微观串行! -----推动了计算机蓬勃发展,将人类引入了多媒体时代。
CPU和MMU
MMU:
- 虚拟内存与物理内存的映射
- 设置修改内存访问级别
page是MMU划分物理内存的最小单位,当我执行2个a.out时,虚拟地址空间2份,其中user空间映射的物理内存需要重新开辟空间,因为进程彼此独立,但kernel虚拟空间在物理内存中只映射一份,因为内核一份,但PCB进程控制块依然2份,不一样。
进程控制块(PCB)
我们知道,每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。 grep -r “task_struct {” /usr/src/linux-headers-3.16.0-30/include/linux/sched.h
/usr/src/linux-headers-3.16.0-30/include/linux/sched.h文件中可以查看struct task_struct 结构体定义。其内部成员有很多,重点掌握以下部分即可:
- 进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,其实就是一个非负整数。
- 进程的状态,有就绪、运行、挂起、停止等状态。
- 进程切换时需要保存和恢复的一些CPU寄存器。
- 描述虚拟地址空间的信息。
- 描述控制终端的信息。
- 当前工作目录(Current Working Directory)。
- umask掩码。
- 文件描述符表,包含很多指向file结构体的指针。
- 和信号相关的信息。
- 用户id和组id。
- 会话(Session)和进程组。
- 进程可以使用的资源上限(Resource Limit)。
进程状态
进程基本的状态有5种。分别为初始态,就绪态,运行态,挂起态与终止态。其中初始态为进程准备阶段,常与就绪态结合来看。
环境变量
环境变量,是指在操作系统(Linux多用户多任务)中用来指定操作系统运行环境的一些参数。通常具备以下特征: ① 字符串(本质) ② 有统一的格式:名=值[:值] ③ 值用来描述进程环境信息。 存储形式:与命令行参数类似。char *[]数组,数组名environ,内部存储字符串,NULL作为哨兵结尾。 使用形式:与命令行参数类似。 加载位置:与命令行参数类似。位于用户区,高于stack的起始位置。 引入环境变量表:须声明环境变量。extern char ** environ;
#include <stdio.h>
extern char **environ;
int main(void)
{
int i;
for(i = 0; environ[i] != NULL; i++){
printf("%s\n", environ[i]);
}
return 0;
}
常见环境变量
按照惯例,环境变量字符串都是name=value这样的形式,大多数name由大写字母加下划线组成,一般把name的部分叫做环境变量,value的部分则是环境变量的值。环境变量定义了进程的运行环境,一些比较重要的环境变量的含义如下: PATH 可执行文件的搜索路径。ls命令也是一个程序,执行它不需要提供完整的路径名/bin/ls,然而通常我们执行当前目录下的程序a.out却需要提供完整的路径名./a.out,这是因为PATH环境变量的值里面包含了ls命令所在的目录/bin,却不包含a.out所在的目录。PATH环境变量的值可以包含多个目录,用:号隔开。在Shell中用echo命令可以查看这个环境变量的值: $ echo $PATH SHELL 当前Shell,它的值通常是/bin/bash。 TERM 当前终端类型,在图形界面终端下它的值通常是xterm,终端类型决定了一些程序的输出显示方式,比如图形界面终端可以显示汉字,而字符终端一般不行。 LANG 语言和locale,决定了字符编码以及时间、货币等信息的显示格式。 HOME 当前用户主目录的路径,很多程序需要在主目录下保存配置文件,使得每个用户在运行该程序时都有自己的一套配置。
环境变量相关函数
getenv()函数 获取环境变量值 函数原型:char *getenv(const char *name); 成功返回环境变量的值,失败NULL(name不存在) setenv()函数 设置环境变量的值 函数原型:int setenv(const char *name, const char *value, int overwrite); 成功0 失败-1 参数overwrite取值: 1 - - 覆盖原环境变量 0 - -不覆盖。(该参数常用于设置新环境变量,如ABC=haha-day-night)
. unsetenv()函数 删除环境变量name的定义 函数原型:int unsetenv(const char *name); 成功0 失败-1 注意事项: name不存在仍返回0(成功),当name命名为”ABC=“时则出错
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *val;
const char *name = "ABD";
val = getenv(name);
printf("1, %s = %s\n", name, val);
setenv(name, "haha-day-and-night", 1);
val = getenv(name);
printf("2, %s = %s\n", name, val);
#if 1
int ret = unsetenv("ABD=");
printf("ret = %d\n", ret);
val = getenv(name);
printf("3, %s = %s\n", name, val);
#else
int ret = unsetenv("ABD");
printf("ret = %d\n", ret);
val = getenv(name);
printf("3, %s = %s\n", name, val);
#endif
return 0;
}
参考
黑马程序员服务器开发课程资料
|