文件的I/O 模型
例如
open()read()
write()
close()
#文件描述符
- 在
I/O
调用中文件描述符是一个非常小的非零整数,常用open()打开,在参数中指定I/O操作的目标文件的路径名 。 - 通常有shell启动的进程会继承3个已打开的文件描述符
例如
:
0为标准输入、
1为标准输出、2位标准错误
上述的3种一般都指向终端。
stdio函数
C 编程语言在执行文件 I/O 操作时,往往会调用 C 语言标准库的 I/O 函数。也将这样一组I/O 函数称为 stdio 函数库,其中包括 fopen()、fclose()、scanf()、printf()、fgets()、fputs()等。stdio 函数位于 I/O 系统调用层(open()、close()、read()、write()等)之上
C 语言程序可以访问命令行参数,数,程序的 main()函数需做如下声明:
int main(int argc ,char*argv[])
argc 变量包含命令行参数的总个数,argv 指针字符串。首个字符串 argv[0],标识程序名本身。
进程
何为进程:
简而言之 ,进程是正在执行的程序实例。执行程序时,内核将程序代码载入虚拟内存,为程序分配空间和记录各种信息(
比如 进程ID、用户ID、组ID以及终止状态等等
)。
进程是一个个实体,内核必须在它们之间共享各种计算机资源。对于像内存这样的受限资源来说,内核一开始会为进程分配一定数量的资源,并在进程的生命周期内,统筹该进程和整个系统对资源的需求,对这一分配进行调整。程序终止时,内核会释放所有此类资源,供其他进程重新使用。其他资源(如 CPU、网络带宽等)都属于可再生资源,但必须在所有进程间平等共享`
进程中内存的的布局
- 逻辑上可以分为以下几个部分
- 文本:程序的指令。
- 数据: 程序使用的静态变量。
- 堆 :程序可在该区域动态分配额为内存。
- 栈 : 随函数的调用、返回而增减一片内存,用于为局部变量和函数调用链接信息分配存储空间
创建进程和执行程序
进程可使用系统调用
fork()
来创建一个新进程。
调用fork()的进程被称作父进程,
修改子进程的内容避讳影响父进程的内容
- 子进程要么去执行与父进程共享代码段中的另一组不同函数,或者,更为常见的情况是使用系统调用 execve()去加载并执行一个全新程序。execve()会销毁现有的文本段、数据段、栈段及堆段,并根据新程序的代码,创建新段来替换它们。
- 一般情况下,书中会使用“执行”一词来指代 execve()及其衍生函数所实施的操作。
进程ID和父进程ID
每一个进程都有唯一的整数型进程标识符(PID)和一个父进程标识符(PPID)属性,用以标识符请求内核创建自己的进程。
进程终止和中止状态
- 进程可使用_exit()系统调用(或相关的eixt() )。
- 向进程传递信号,将其
杀死
。
无论怎样结束进程,一个非负小整数,可供父进程的write()系统调用检测
进程的用户和组标识符(凭证)
- 真实的用户ID和组ID:用来标识进程所属的用户和组
- ID:用来标识进程所属的额外组。新进程从其父进程处继承补充组 ID。登录shell 则从系统组文件中获取其补充组 。
- ID和组ID: 进程在访问受保护资源(比如,文件和进程间通信对象)
时,会使用这两个 ID(并结合下述的补充组 ID)来确定访问权限。