进程的概念及应用
进程:占用内存空间正在运行的程序
CPU核:CPU核的个数与运行的进程数相同,若进程超过核数,进程将分时使用CPU资源.(cpu运算速度极快,所以平时感觉所有进程好像是在同时运行)
查看进程:ps au
并发服务器的实现方法
- 多进程服务器:通过创建多个进程提供服务
- 多路复用服务器:通过捆绑并统一管理I/O对象提供服务
- 多线程服务器:通过生成与客户端等量的线程提供服务
创建进程
使用fork()函数创建进程,它将会创建调用的进程副本,会复制正在运行的父进程为一个全新的子进程,2个进程都将执行fork函数调用后的语句
父进程:fork函数返回子进程ID(原进程)
子进程:fork函数返回0
#include <stdio.h>
#include <unistd.h>
int gval = 10;
int main(int argc, char *argv[])
{
pid_t pid;
int lval = 20;
gval++, lval += 5;
pid = fork();
if(pid == 0) //这是子进程
{
gval += 2, lval += 2;
} else {
gval -= 2, lval -= 2;
}
if(0 == pid) {
printf("Child Proc: [%d, %d]\n", gval, lval);
} else {
printf("Parent Proc: [%d, %d]\n", gval, lval);
}
return 0;
}
以上例程编译运行结果:
Parent Proc: [9, 23]
Child Proc: [13, 27]
可以看出运行fork创建进程后,父子进程拥有完全独立的内存结构。
僵尸进程
进程工作完成后(main函数中的程序执行完成后)应该被销毁,但有时这些程序变成僵尸进程,占用系统中的重要资源,这种状态下的进程称为僵尸进程。
产生僵尸进程的原因:
向exit函数传递的值和main函数的return语句传递的值都会传递给操作系统,而操作系统不会销毁子进程,直到把这些值传递给产生子进程的父进程,处在这种状态下的进程就是僵尸进程,也就是说正是操作系统将子进程变成了僵尸进程。如何销毁:"应该向创建子进程的父进程传递子进程的return语句返回值或者exit语句的参数 "
如果父进程未主要要求获取子进程的状态值,操作系统则一直保存,让子进程一直处于僵尸进程,也就是说谁创造的孩子,谁负责带走。
//vim zombie.c
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
pid_t pid = fork();
if(pid == 0){ //子进程
puts("我是子进程");
} else {
printf("我是父进程\n我的进程ID为%d", pid);
sleep(10);
}
if(pid == 0)
puts("结束子进程\n");
else
puts("结束父进程\n");
return 0;
}
[root@11_centos C]# gcc zombie.c -o zombie
[root@11_centos C]# ./zombie
我是父进程
我是子进程
结束子进程
我的进程ID为32010
结束父进程
//在父进程sleep的过程中通过ps au可以查看到子进程并未结束,而是等父进程全部完成后,子进程才真正销毁。
通过wait销毁僵尸进程
//vim wait.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int status;
pid_t pid = fork();
if(pid==0) {
return 3;
} else {
printf("子进程的进程ID:%d\n", pid);
pid=fork();
if(pid == 0)
{
exit(7);
} else {
printf("子进程的进程ID:%d\n", pid);
wait(&status);
if(WIFEXITED(status)) {
printf("子进程1终止:%d\n", WEXITSTATUS(status));
}
wait(&status);
if(WIFEXITED(status)) {
printf("子进程2终止:%d\n", WEXITSTATUS(status));
}
sleep(20);
}
}
return 0;
}
[root@0_11_centos C]# ./wait
子进程的进程ID:1973
子进程的进程ID:1974
子进程1终止:7
子进程2终止:3
//这就是wait函数消灭僵尸进程的方法,调用wait函数时,如果没有已终止的子进程,,那么程序将会阻塞直到有子进程终止,所以要慎重使用。
WIFEXITED 子进程正常终止时返回 true
WEXITSTATUS 返回子进程终止时返回的值