什么是进程
进程的经典定义就是一个执行中的的程序的实例。系统中的每个程序都是运行在某个进程的上下文中的。
上下文是有程序正确运行所需状态组成的。
这个状态包括存储器中的程序的代码和数据, 他的栈,通用寄存器的内容、程序计数器、环境变量以及打开文件描述符的集合。
每一个进程都是一段逻辑控制流,多个流分时间片并发运行。
每一个进程都拥有独立的虚拟地址空间。
我们使用fork这个系统调用创建父子进程。
#include<sys/types.h> pid_t fork(void); 返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
在fork之后exec之前两个进程用的是相同的物理空间,子进程的代码段、BSS段、数据段、堆栈都是指向父进程的物理空间,但虚拟地址不同。
直到父子进程行为不同时才为子进程分配新的物理内存。
使用waitpid回收子进程
#include<sys/types.h> #include<sys/wait.h> pid_t waitpid(pid_t pid,int * status,int options);
如果没有wait或waitpid回收子进程将出现僵尸进程。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
什么是线程
线程就是运行在进程上下文中的逻辑流。一个进程可以同时运行多个线程,线程有内核自动调度。
每个线程都有它自己的线程上下文,包括一个唯一的整数线程ID、栈、栈指针、程序计数器、通用目的寄存器和条件码。
所有的线程共享该进程的整个虚拟地址空间。
主线程创建的线程称为对等线程。当主线程执行慢速系统调用时(read、sleep)或被系统计时器中断时发生线程上下文切换。
线程通过pthread_create创建对等线程。
#include<pthread.h> int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, (void*)(*start_rtn)(void*), void *arg);