进程是操作系统资源管理的最小单位。
进程的概念:
进程是操作系统资源分配的基本单位。进程和程序的区别在于进程是动态的,程序是静态的,进程是运行中的程序,程序是保存在硬盘上的可执行的代码。进程内部又划分了许多线程,线程在进程内部,它是比进程更小的能独立运行的基本单位,线程基本上不拥有系统资源,它与同属于一个进程的其他线程共享进程拥有的全部资源。进程在运行过程中拥有独立的内存单元,其内部的线程共享这些内存。一个线程可以创建或撤销另一个线程,同一个进程中的多个线程可以并行执行。
进程标识:
每一个进程都有唯一的进程ID,进程ID是一个非负数,除了进程ID每个进程还有其他的标识。可以通过函数来获得:
pid_t getpid(id) 获得进程id
pid_t getppid(id) 获得进程的父进程id
pid_t getuid(id) 获得进程的实际用户id
pid_t geteuid(id) 获得进程的有效用户id
pid_t getgid(id) 获得进程的实际组id
pid_t getegid(id) 获得进程的有效组id
Linux 进程的结构:
代码段 数据段 堆栈段
代码段 存放程序的可执行代码
数据段 存放程序的全局变量、常量、静态变量
堆栈段 堆用于存放动态分配的内存变量,栈用于函数调用,存放函数参数,函数内部定义的局部变量
Linux进程状态:
可运行状态 :正在运行或在运行队列中等待运行
可中断等待状态 :进程在等待某个事件完成,等待过程中可以被信号或定时器唤醒
不可中断等待状态 :进程在等待某个事件完成,等待过程中不可以被信号或定时器唤醒
僵死状态:进程已终止,但进程描述符依旧存在直到父进程调用wait()后释放
停止状态:进程因为收到了SIGSTOP SIGSTP SIGTIN SIGOUT信号后停止运行或者该进程正在被跟踪
进程控制
fork() 用于创建一个新的进程
exit() 用于终止一个进程
exec() 用于执行一个应用程序
wait() 将父进程挂起,等待子进程终止
getpid() 获取当前进程的ID
nice() 改变进程的优先级
创建进程
fork()函数:
pid_t fork(void)
该函数有两个返回值,即调用一次返回两次。成功调用fork函数后,当前进程已经分裂为两个进程,即父进程和子进程,父子进程在调用fork的地方分开,fork函数的两个返回值,一个是父进程调用fork函数后的返回值,这个返回值的刚创建的子进程的ID,;另一个是子进程中fork函数的返回值,该返回值是0。有两个返回值的前提是进程创建成功,如果创建失败则返回-1。
1
2 #include<stdio.h>
3 #include<sys/types.h>
4 #include<unistd.h>
5
6 int main()
7 {
8 pid_t pid;
9
10 printf("Process Cration Study\n");
11 pid = fork();
12 switch(pid)
13 {
14 case 0:
15 printf("Child process, childID %d, ParentID %d\n", pid, getppid());
16 break;
17 case -1:
18 perror("Process child failed!\n");
19 break;
20 default:
21 printf("Parent process is running, childID %d , parentID %d\n",pid,getppid());
22 break;
23 }
24 exit(0);
25 }
~
"GOver.c" 25L, 437C 24,4-7 全部
两次运行程序的结果如下:
以上两次运行结果都是父进程先运行,一般情况下,fork之后是父进程先执行还是子进程先进行是不确定的,取决于内核的调度方法。我们也可以让父进程与子进程交替执行,将代码做如下修改:
int main()
{
pid_t pid;
char *msg;
int k;
pid = fork();
switch(pid)
{
case 0:
msg = "Child process is running!\n";
k = 3;
break;
case -1:
perror("Process creation failed!\n");
break;
default:
msg = "Parent process is running!\n";
}
while(k > 0)
{
puts(msg);
sleep(1);
k--;
}
exit(0);
}
运行情况如下:
vfork()函数
它也可以用来创建一个进程,vfork与fork一样都是调用一次,返回两次。fork创建的子进程只是完全复制父进程的资源,子进程独立于父进程;vfork创建一个子进程共享父进程的地址空间,该子进程对该地址空间的数据的任何修改都能被父进程所见;使用fork函数创建的子进程,父子进程的执行顺序由系统的调度算法决定,但是vfork保证子进程先运行,只有它调用exec或exit后父进程才会被调度。vfork不会拷贝父进程的资源空间,大大减小了系统开销。