一、 UNIX 基础知识
- UNIX 体系结构
内核(kernel): 操作系统,一种搞管理的软件,控制,控制计算机硬件资源,提供程序运行环境
系统调用(system call):内核的接口, 共用函数库构建在系统调用接口上,应用程序既可使用公用函数库,也可使用系统调用
shell:命令行解释器,读取用户输入,然后执行命令 ---- 是一种比较通用的概念
bash: 特指 Linux 的 shell ---- 具体的一个
那操作系统作为一个管理者,又怎样管理的呢?
先描述,在组织
描述:进程PCB
组织:链表(创建一个进程,就将 PCB 插入链表中,进程终止,把该进程对应的 PCB 从链表中删除)
- 文件描述符
一个小的非负整数 内核用以标示一个特定进程正在访问的文件
- 内核打开一个现有文件或者创建一个新文件时 都会返回一个文件描述符,在读、写文件时,可以使用这个文件描述符
- 每当运行一个新程序时,所有的 shell 都为其打开 3 个文件描述符:
标准输入(standard input)
标准输出(standard output)
标准错误(standard error)- 其中任何一个或所有这 3 个描述符都可以被重定向到某个文件
- 进程
程序:一个存储在磁盘某个目录中的可执行文件
进程:一个运行起来的程序(程序的执行实例)
程序运行之后,相应代码将会加载到内存,即使删除对应的可执行程序,也不影响程序的继续运行 因为可执行程序存储在磁盘上
如何描述进程? ---- PCB (在 Linux 中 叫做 task_struct)
二、进程 PCB 最起码要包含哪些信息?
- 进程ID:进程的身份标示,同一台主机上,每个进程都有一个非负整型表示的唯一进程ID (pid)
虽然是唯一的,但是进程ID是可以复用的。当一个进程终止后,其进程 ID 就成为复用的候选者。大多数 UNIX 系统实现延迟复用算法,使得赋予新建进程的 ID 不同于最近终止进程所使用的 ID 。这防止了将新进程误认为是使用同一 ID 的某个已终止的先前进程
- 一组内存指针
指向代码和代码所依赖的数据 - 辅助操作系统进行进程调度的属性
a) 优先级:决定进程被调度到 CPU 上执行的顺序
b) 上下文:保存了进程上次在 CPU 上执行的现场
三、进程终止
- 正常终止
- 从 main 返回
在 main 函数内执行 return 语句,这等效于调用 exit- 调用 exit
包括调用各终止处理程序,然后关闭所有标准 IO 流- 调用 _exit 或 _Exit
为进程提供一种无需运行终止处理程序或信号处理程序而终止的方法。不冲洗标准 IO 流。- 最后一个线程从启动例程中返回
执行 return 语句。但该线程的返回值不用作进程的返回值。当最后一个线程从其启动例程返回时,该进程以终止状态 0 返回。- 从最后一个线程中调用 pthread_exit
进程终止状态总是 0。
- 异常终止
- 调用 abort
产生一个 SIGABRT 信号- 接到一个信号
- 最后一个线程对“取消”请求作出响应
默认情况下,“取消”以延迟方式发生:一个线程要求取消另一个线程,若干时间后,目标线程终止。
不管进程如何终止,最后都会执行内核中的同一段代码。这段代码为相应进程关闭所有打开描述符,释放它所使用的存储器等。
四、main 函数
我们都知道, C程序总是从 main 函数开始执行,main 函数作为程序的入口,一个 C 程序有且只有一个 main 函数
- main 函数原型如下:
int main(int argc, char* argv[], char* envp[]);
- 参数解释
argc 是命令行参数的数目
argv 是指向参数的各个指针所构成的数组
envp 是环境变量
每个程序都有一张环境表,与参数表一样,环境表也是一个字符指针数组,其中,每个指针包含一个以 NULL 结束的 C 字符串的地址(结束的标志),环境变量是一个个的键值对结构。
我们来写个小程序打印mian函数的参数与环境变量
// 打印 main 函数的参数和环境变量
//
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[], char* env[])
{
if(argc != 2)
{
printf("Usage: ./a.out [arguments]\n");
exit(1); // 需要包含头文件 stdlib.h
}
int i = 0;
for(i = 0; i < argc; ++i)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
i = 0;
while(env[i] != NULL)
{
printf("%s\n", env[i]);
++i;
}
return 0;
}
程序运行结果:
由上图,我们很明显的看到了环境变量是一个个的键值对结构。