1.物理地址-------MMU------》虚拟地址----启动进程---->进程空间地址
2.Uxworks FreeRTOS Ucos/2
3. volatile(不优化) register(尽量优化)
4.每个进程在内核中都有一个进程控制块来维护相关的信息, Linux内核的进程控制块是tast_struct结构体
5.两个重要的系统调用 fork(刀叉, 民间的, 分叉) 和 exec(执行)
fork的作用 :根据一个现有的进程复制出一个新进程, 原来的进程称为父进程,新的进程称为子进程
例外 : 子进程PCB中的进程id和父进程是不同的
6.exit 和 _exit函数用于终止一个进程
函数原型 : #include <stdlib.h> void exit(int status);
#include <unistd.h> void _exit(int status);
区别 :exit是标准C的库函数,负责完成标准C的其他库函数留下的清理工作。
_exit是UNIX系统函数,是exit系统调用的包装,调用_exit函数时直接进入内核终止掉当前进程,释放分配的内存,关闭文件描述符, 不需要做用户空间的清理工作。
扩展 : exit在做完清理工作后最终也是调用_exit终止当前进程的
7.异常终止 :进程收到一个信号,然后内核把进程强行终止掉了, 进程并么有执行 _exit系统调用,也没有退出状态。(例如: Ctrl-C 或着Kill命令终止一个进程)
8.可以使用echo 命令查看这个环境变量的值。
9.如果给出name要在环境变量表中查找它对应的value, 可以用getenv函数
函数原型 : #include <stdlib.h> char *getenv(const char *name);
返回值 : getenv的返回值是指向value的指针, 若未找到则为NULL
10. 修改环境变量的函数 :
函数原型 : int setenv(const char *name, const char *value, int rewrite);
void unsetenv(const char *name);
putenv 和 setenv 函数若成功返回为0, 若出错返回非0
setenv将环境变量name的值设置为value, 如果已存在环境变量name. 那么
若rewirite非0, 则覆盖原来的定义
若rewrite为0, 则不覆盖原来的定义, 也不返回错误
unsetenv 删除name的定义。 即使name么有定义也不返回错误。
11. 可剥夺型内核和不可剥夺型内核
12.fork函数
函数原型 : #include <sys/types.h> #include <unistd.h> pid_t fork(void)
返回值 : 调用失败返回-1. 调用成功有两个返回值(pid == 0)执行子进程,(pid > 0)执行父进程
当父进程结束,程序直接返回。
可以使用usleep(0)在两个进程间故意切换
fork函数的特点 : 调用一次 , 返回两次
注意: fork在子进程中返回0, 子进程仍可以调用getpid函数得到自己的进程id, 也可以调用getppid函数得到父进程的id。在父进程中可以用getpid函数得到自己的进程id,然而想要得到子进程的id,只有将fork的返回值记录下来, 别无它法。
fork的另一个特性 : 所有有父进程打开的描述符都被复制到子进程中。(即file结构体的引用计数要增加)
gdb调式:
set follow-fork-mode child 命令设置gdb在fork之后跟踪子进程
set follow-fork-mode parent 跟踪父进程。
13.exec函数 (Executive)执行
提示: 调用exec前后該进程的id并未改变
函数原型: #include <unistd.h>
(重点)int execvp(const char *file, char *const argv[]);
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
补充: 最少有两个指针, argv最后一个为 NULL
扩展 : exec函数只有出错的返回值而没有成功的返回值,,出错返回-1
14.僵尸进程: 如果一个进程已经终止, 但是它的父进程尚未调用wait或waitpid对它进行清理, 这时的状态称为僵尸进程
15.如果一个父进程终止,而它的子进程还存在,则这些子进程的父进程改为init进程
init进程: 一个特殊进程, 通常程序文件/sbin/init 进程id是1,在系统启动时负责启动各种系统服务, 之后就负责清理子进程, 只要有子进程终止, init就会调用wait函数清理它
函数原型: #include <sys/types.h> #include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
返回值 : 如果调用成功返回子进程id,调用失败返回-1
父进程调用wait或waitpid时可能会:
阻塞(如果它的所有子进程都还在运行)
带子进程的终止信息立即返回(如果一个子进程已终止,正等待父进程读取其终止信息)
出错立即返回(如果它么有子进程)
这两个函数的区别 :
如果父进程的所有子进程都还在运行,调用wait将使父进程阻塞,而调用waitpid时如果在options参数中指定WNOHANG可以使父进程不阻塞而立即返回0
wait等待第一个终止的子进程,而waitpid可一个通过pid参数指定等待哪一个子进程
wait函数作用 ;
使用wait和waitpid可以获得子进程的终止信息。
可以使父进程阻塞等待子进程终止,起到进程间同步的作用
清理子进程
扩展 ; 低字节判断信号, 高字节判断退出状态
英语 ; abnormally(异常) Executive(执行)