Linux并发处理方式——多进程fork实现

Linux并发处理方式——多进程fork实现

运行环境:Ubuntu18.04

前言:
在Linux环境下进程是很重要的知识点,它可以实现在一个应用程序下处理并发问题,并发处理的方式包括多进程、多线程和多路复用,前两者会更多地占用系统的资源。下面简单地利用server和client实现,server同时服务多个client。

一、基本介绍

1、fork、vfork
(1)fork()系统调用会创建一个新的子进程,这个子进程是父进程的一个副本。这也意味着,系统在创建新的子进程成功后,会将父进程的文本段、数据段、堆栈都复制一份给子进程,但子进程有自己独立的空间,子进程对这些内存的修改并不会影响父进程空间的相应内存。这时系统中出现两个基本完全相同的进程(父、子进程),这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。如果需要确保让父进程或子进程先执行,则需要程序员在代码中通过进程间通信的机制来自己实
现。

(2)vfork()并不将父进程的地址空间完全复制到子进程中,如果子进程想尝试修改数据域(数据段、堆、栈),这时候才会进行复制。vfork()会保证子进程先运行。但是这里存在一个问题就是,如果子进程依赖父进程的一些参数就会产生死锁了。

2、进程僵死问题
当一个子进程在运行的的过程中进行中断或者没有进行返回时,则会产生进程僵死的问题。在这个采用waitpid和signal进行解决问题。
(1)wait、waitpid
wait
pid_t wait(int *status)

①status
如果参数status的值不是NULL,wait就会把子进程退出时的状态取出并存入其中,这是一个整数值(int),指出了子进程是正常退出还是被非正常结束的。

waitpid
pid_t waitpid(pid_t pid,int *status,int options)

①pid解释
pid>0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。
pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样。
pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。
pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。

②status
这个是一个状态值,会把状态信息写到它指向的位置,一般不关心这个值。

③options
0,则代表阻塞等待子进程结束,再回收,跟wait一样;
WNOHANG,则不再等待,如果要回收的子进程都在运行,则直接返回0,然后接着执行后续程序;
WUNTRACED,如果子进程由于被停止产生的SIGCHLD,waitpid则立即返回;
WCONTINUED,如果子进程由于被SIGCONT唤醒而产生的SIGCHLD,waitpid则立即返回。

④函数返回值
如果没有子进程或其它错误原因,则返回-1;如果成功回收子进程,则返回回收的那个子进程的ID;如果第三个参数为WNOHANG,且子进程都在运行,则返回0。

waitpid( -1, NULL,0) 与 wait( NULL )是等效的,都是阻塞等待回收所有子进程。

(2)signal

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

第一个参数signum:指明了所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。
第二个参数handler:描述了与信号关联的动作,它可以取以下三种值:
SIG_IGN :忽略该信号。
SIG_DFL :表示恢复对信号的系统默认处理。不写此处理函数默认也是执行系统默认操作。
sighandler_t类型的函数指针 :此函数必须在signal()被调用前申明,handler中为这个函数的名字。当接收到一个类型为sig的信号时,就执行handler 所指定的函数。(int)signum是传递给它的唯一参数。执行了signal()调用后,进程只要接收到类型为sig的信号,不管其正在执行程序的哪一部分,就立即执行func()函数。当func()函数执行结束后,控制权返回进程被中断的那一点继续执行。

3、文件IO操作

请参考博客:https://blog.youkuaiyun.com/weixin_45062087/article/details/118880374

二、具体代码

1、fork_server

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <getopt.h>
#include <ctype.h>
#include <signal.h>
#include <sys/wait.h>

//#define PORT 9988

void sig_child(int sign)
{
   
	pid_t	pid;
	int	stat = 0;
	for(;;)
	{
   
		pid = waitpid(-1, &stat
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

X 、case

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值