1. 引言我们知道,每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是 task_struct 结构体。现在我们全面了解一下其中都有哪些信息。目前读者并不需要理解这些信息的细节,在随后几章中讲到某一项时会再次提醒读者它是保存在PCB中的。 fork 和exec 是本章要介绍的两个重要的系统调用。fork 的作用是根据一个现有的进程复制出一个新进程,原来的进程称为父进程(Parent Process),新进程称为子进程(Child Process)。系统中同时运行着很多进程,这些进程都是从最初只有一个进程开始一个一个复制出来的。在Shell下输入命令可以运行一个程序,是因为Shell进程在读取用户输入的命令之后会调用fork 复制出一个新的Shell进程,然后新的Shell进程调用exec 执行新的程序。我们知道一个程序可以多次加载到内存,成为同时运行的多个进程,例如可以同时开多个终端窗口运行 图 30.1. fork/exec 在第 3 节 “open/close”中我们做过一个实验:用 2. 环境变量先前讲过, exec 系统调用执行新程序时会把命令行参数和环境变量表传递给main 函数,它们在整个进程地址空间中的位置如下图所示。图 30.2. 进程地址空间 和命令行参数 argv 类似,环境变量表也是一组字符串,如下图所示。图 30.3. 环境变量 libc 中定义的全局变量environ 指向环境变量表,environ 没有包含在任何头文件中,所以在使用时要用extern 声明。例如:例 30.1. 打印环境变量 #include <stdio.h> 执行结果为 由于父进程在调用$ ./a.out fork 创建子进程时会把自己的环境变量表也复制给子进程,所以a.out 打印的环境变量和Shell进程的环境变量是相同的。按照惯例,环境变量字符串都是 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 当前用户主目录的路径,很多程序需要在主目录下保存配置文件,使得每个用户在运行该程序时都有自己的一套配置。 用 environ 指针可以查看所有环境变量字符串,但是不够方便,如果给出name 要在环境变量表中查找它对应的value ,可以用getenv 函数。#include <stdlib.h> getenv 的返回值是指向value 的指针,若未找到则为NULL 。修改环境变量可以用以下函数 #include <stdlib.h> putenv 和setenv 函数若成功则返回为0,若出错则返回非0。
例 30.2. 修改环境变量 #include <stdlib.h> 可以看出,Shell进程的环境变量$ ./a.out PATH 传给了a.out ,然后a.out 修改了PATH 的值,在a.out 中能打印出修改后的值,但在Shell进程中PATH 的值没变。父进程在创建子进程时会复制一份环境变量给子进程,但此后二者的环境变量互不影响。
|
|
来自: XeonGate > 《Linux编程接口》