1、僵尸进程
僵尸进程是很特殊的一种进程,几乎不占用内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表找保留一个位置,记载该进程的退出状态灯信息。它需要父进程来给他收尸,如果他的父进程没有安装SIGCHLD信号处理函数调用wait活waitpid()等待子进程结束,又没有显示忽略该新信号,那么该僵尸进程就一直保持僵尸状态,如果父进程结束了,那么init进程会自动接收这个子进程,为他收尸,他还是会被清除的,但是如果父进程是一个循环,则该子进程就会一直保持将是状态。
避免僵尸进程的方法:
1. 在SVR4中,如果调用signal或者sigset将SIGCHLD的配置设置为忽略,则不会产生僵死子进程,另外使用SVR4版的sigaction,则可以设置SA_NOCLDWAIT避免子进程僵死。
2. 调用fork两次
3. 用waitpid等待子进程返回
2、fork函数
一个进程,包括代码,数据和分配给进程的资源,fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用fork()函数之后,系统先给新的进程分配资源,例如存储数据和代码的空间,然后把原来进程的所有值都复制到新的进程中,只有少数值与原来的进程值不同,相当于克隆了一个自己。
1./* 2. * fork_test.c 3. * version 1 4. * Created on: 2010-5-29 5. * Author: wangth 6. */ 7.#include <unistd.h> 8.#include <stdio.h> 9.int main () 10.{ 11. pid_t fpid; //fpid表示fork函数返回的值 12. int count=0; 13. fpid=fork(); 14. if (fpid < 0) 15. printf("error in fork!"); 16. else if (fpid == 0) { 17. printf("i am the child process, my process id is %d/n",getpid()); 18. printf("我是爹的儿子/n");//对某些人来说中文看着更直白。 19. count++; 20. } 21. else { 22. printf("i am the parent process, my process id is %d/n",getpid()); 23. printf("我是孩子他爹/n"); 24. count++; 25. } 26. printf("统计结果是: %d/n",count); 27. return 0; 28.}
运行结果是:
i am the child process, my process id is 5574
我是爹的儿子
统计结果是: 1
i am the parent process, my process id is 5573
我是孩子他爹
统计结果是: 1
在语句fpid=fork()之前,只有一个进程在执行这段代码,在这条语句之后,就编程了两个进程了,而且两个进程都有fpid这个参数,而且值不一样,fork函数执行以后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程,在子进程中fork函数返回的值为0在父进程中返回值为子进程的进程ID,其实就相当于链表,进程形成了链表,父进程的fpid指向子进程的进程ID,子进程没有子进程则fpid为0
fork出错可能有两种原因:
1)当前的进程数已经达到了系统规定的上线,这是errno的值被设置为EAGAIN
2)系统内存不足,这是errono的值被设置为ENOMEM
3、简述Unix/Linux系统中使用socket库编写服务器端程序的流程
TCP socket通信,服务器端流程如下:
a. 创建serverSocket
b. 初始化serverAddr(服务器地址)
c. 将socket和serverAddr绑定 bind
d. 开始监听 listen
e. 进入while 循环,不断的accept接入客户端的socket 进行读写操作
f. 关闭serverSocket
客户端流程:
a. 创建clientSocket
b. 初始化serverAddr
c. 链接到服务器 connect
d. 利用write和read进行读写操作
e. 关闭clientSocket