进程控制理论:
进程定义:
进程是一个具有一定独立功能的程序的一次运行活动。
进程特点:
动态性、并发性、独立性、异步性
进程的三大状态:
进程ID:PID,标识进程的唯一数字
父进程的ID:PPID
启动进程的用户ID:UID
进程互斥:
当有若干进程都要使用某一资源时,但该资源在同一时刻最多允许一个进程使用,这时其他进程必须等待,直到占用该资源者释放了该资源为止。
临界资源:
操作系统中将同一时刻只允许一个进程访问的资源称为临界资源。
临界区:
进程中访问临界资源的那段程序代码称为临界区。为实现对临界资源的互斥访问,应保证诸进程互斥地进入各自的临界区。
进程同步:
一组进程按一定的顺序执行的过程称为进程间的同步.具有同步关系的这组进程称为合作进程,最为有名的是生产者和消费者进程。
进程调度:
按一定算法,从一组待运行的进程中选出一个来占有CPU运行。
在操作系统中,常见的调度算法有:
1. 先来先服务
2. 短进程优先调度
3. 高优先级优先调度
4. 时间片轮转法
按调度时机,调度又可分为:
• 抢占式调度,优先级高的进程会抢占优先级低的进程进入CPU运行。
• 非抢占式调度
死锁:
多个进程因竞争资源而形成一种僵局,导致这些进程都无法继续往前执行。
获得进程ID
函数原形:
pid_t getpid(void);
函数功能:
返回正在调用该函数的进程的ID。
所属头文件:
#include <sys/types.h>
#include <unistd.h>
返回值:
返回调用该函数的进程的ID
**进程退出:**exit(0);
父进程可以用”return 0”或”exit(0)”退出,但是子进程只能用”exit(0)”退出。
例程:
/* 本文件返回进程的ID */
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
void main()
{
int pid;
pid = getpid();
printf("the process id is %d.\n");
}
创建进程(1)
函数原形:
pid_t fork(void);
函数功能:
创建一个新的子进程,新进程是调用该函数进程的复制。新进程为子进程,原进程为父进程。子进程从fork函数之后开始运行。
所属头文件:
#include <unistd.h>
返回值:
若成功,在父进程中返回新的子进程的ID,在子进程返回0;若失败,返回-1.
创建进程(2)
函数原形:
pid_t vfork(void);
函数功能:
创建一个子进程,并阻塞父进程,在子进程运行结束后,再运行父进程。
所属头文件:
#include <sys/types.h>
#include <unistd.h>
返回值:
若成功,在父进程中返回新的子进程的ID,在子进程返回0;若失败,返回-1.
fork和vfork不同之处:
1. fork:子进程拥有独立的数据段,堆栈。 vfork:子进程与父进程共享数据段,堆栈。
2. fork:父、子进程的执行次序不确定。 vfork:子进程先运行,父进程后运行
进程等待
函数原形:
pid_t wait(int *status);
函数功能:
挂起调用它的进程,直到其子进程结束
所属头文件:
#include <sys/types.h>
#include <sys/wait.h>
返回值:
若成功,返回结束的子进程的ID;若失败,返回-1。
参数说明:
status:记录子进程的退出状态,可以为NULL
执行程序
函数原形:
int execl(const char *path, const char *arg, …);
函数功能:
运行可执行文件。在执行该函数之后,程序中的代码段就变成了函数中调用的可执行文件的代码,原代码就不执行了。
所属头文件:
#include <unistd.h>
返回值:
若成功,不返回;若失败,才返回。
参数说明:
path: 运行的可执行文件的路径。
arg:arg1、arg2等等参数都是可执行文件运行需要的参数。最后一个一定是NULL。
例程:
/* 本文件是多进程程序设计的相关代码 */
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
void main()
{
pid_t pid;
pid = fork(); //先运行父进程
//pid = vfork();//阻塞父进程
printf("PID is %d.\n", pid);
if (pid > 0)
{
//操作1,父进程的操作
wait(NULL);//进程停止,先运行子进程,后运行父进程
printf("this is parent process.\n");
}
else
{
//操作2,子进程的操作
execl("/bin/ls", "ls", "/home", NULL);//执行程序的函数,相当于执行:"ls /home"
printf("this is child process.\n"); //execl之后代码不再执行
}
exit(0);//进程退出函数
}