一.进程的基本概念归结:具有以下4个要素
1.要有一段程序供该进程运行。
2.进程专用的系统堆栈空间。
3.进程控制快,在Linux中的具体实现是task_struct结构。
4.具有独立的存储空间。
Linux操作系统包括三种不同类型的进程,每种进程都有自己的特点和属性:
1.交互进程:由一个shell启动的进程。交互进程既可以在前台运行,也可以在后台运行。
2.批处理进程:这种进程和终端没有联系,是一个进程序列。
3.监控进程(也称守护进程):Linux系统启动时启动的进程,并在后台运行。
二.进程控制块:在Linux中,每隔进程在创建是都会被分配一个数据结构,称为进程控制块(process control block,简称PCB)。PCB是为了系统为了管理进程设置的一个专门的数据结构,用它来记录进程的外部特征,描述进程的运动变化过程。系统利用PCB来控制和管理进程,所以PCB是系统感知进程存在的位移标志。进程与PCB是一一对应的关系。
2.1获得进程的ID:
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
函数返回:调用进程的进程ID。
三.进程控制的相关函数:
3.1派生一个进程:
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
返回:若成功,父进程中返回子进程ID,子进程中返回0:若出错则返回-1.
fork系统调用的作用是赋值一个进程。当一个进程调用他,完成后就出现两 个几乎一模一样的进程。我们也由此得到了一个新进程。由fork创建的新进 程被成为子进程(child process),而将原来的进程称为父进程(parent process)。子进程是父进程的一个拷贝,即子进程从父进程得到了数据段和 堆栈段的拷贝,这些需要分配新的内存:而对于只读的代码段,通常使用共 享内存的方式访问。fork返回后,子进程和父进程都从调用fork函数的下一 条语句开始执行。至于是父进程先执行还是子进程先执行是不确定的。取决 与内核所使用的调度算法。如果需要父、子进程之间相互同步,则要求某种 形式的进程间通信。
fork函数的主要用途是:
3.1.1:一个进程希望复制自身,从而父子进程能同时执行不同段的代 码。
3.1.2:进程想执行另外一个程序
#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);
返回:与fork函数相同。父进程中返回子进程的进程号,在子进程中返回 0,若出错则返回-1.fork函数与vfork函数之间是有区别的。fork函数要拷贝 父进程的数据段:而vfork则不需要完全拷贝父进程的数据段,在子进程没 有exec或exit之前,子进程与伏击昵称共享数据段。fork不对父子进程的执 行次序进行任何限制:而在vfork调用中,子进程先运行,父进程挂起,直 到子进程调用了exec或exit之后,父子进程的执行次序才不再有限制。所以 vfork函数创建出来的严格意义上说是一个线程。
3.2exec函数:
#include <unstd.h>
int execl(const char* pathname, const char* arg, ...);
int execlp(const char* filename, const char* arg, ...);
int execle(const char* pathname, const char* arg, ..., char* const envp[]);
int execv(const char* pathname, char* const argv[]);
int execvp(const char* filename, char* const argv[]);
int execve(const char* pathname, char* const argv[], char* const envp[]);
6个函数返回:若成功则无返回值,如出错则返回-1.
其中只有execve函数才是真正意义上的系统调用,其他都是在此基础上经过 包装的库函数。exec函数族的作用是根据指定的文件名找到可执行文件,并 用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执 行文件。这里的可执行文件既可以是二进制问家你,也可以是任何Linux下 可执行的脚本文件。与一般情况不同exec函数族的函数执行成功后不会返 回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容 取代,只是进程ID等一些表面殇的信息人保持原样,调用失败才会返回一 个-1,从原程序的调用点接着往下执行。
#include <stdio.h>
void perror(const char* s);
参数s所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因 依照全局变量errno的值来决定要输出的字符串。
注意:如果用到了exec函数族,一定记得要使用错误判断语句。因为与其他 系统调用相比,exec很容受伤,被执行文件的位置,权限等很多因素都能导 致该调用的失败。最常见的错误是:
3.2.1找不到文件或路径,此时errno被设置为ENOENT。
3.2.2数组argv和envp忘记使用NULL结束,此时errno被设置为EFAULT 3.2.3没有要队执行文件的运行权限,此时errno被设置为EACCES。
3.3:exit和_exit函数:
#include <stdlib.h>
void exit(int status);
#include <unistd.h>
void _exit(int status);