Linux系统编程---8(全局变量异步I/O,可重入函数)

探讨了在多进程环境中,全局变量与异步I/O交互导致的问题,特别是在信号捕捉函数中修改全局变量时可能出现的竞争条件。介绍了如何使用锁机制解决此类问题,并强调了在编程中应注意全局变量的异步I/O可能导致的错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

全局变量异步 I/O

分析如下父子进程交替 数数 程序。当捕捉函数里面的 sleep 取消,程序即会出现问题。请分析原因。

#include<stdio.h> 
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>

intn=0,flag=0; 

void  sys_err(char*   str) 
{ 
	perror(str); 
	exit(1); 
} 
void	do_sig_child	(int	num) 
{
	printf("I	am	child %d\t%d\n",getpid(),n);
	 n+=2;
	  flag=1; 
	  sleep(1); 
} 
void	do_sig_parent	(int	num)
{
	  printf("I	am	parent%d\t%d\n",getpid(),n);
	   n+=2;
	   flag=1;
	  	  sleep(1); 
} 
int	main(void) 
 {
  pid_tpid;
struct	sigaction	act;
if((pid=fork())<0)
 sys_err("fork");
	else	if(pid>0)
		   {
		  		 n=1;
				sleep(1);
				 act.sa_handler	=	do_sig_parent; 
				sigemptyset(&act.sa_mask); 
				 act.sa_flags=0;
				 sigaction(SIGUSR2,&act,NULL); //注册自己的信号捕捉函数 父使用 SIGUSR2 信号 do_sig_parent(0); 
				 while(1)
				 { 
						/*waitforsignal*/;
					 if(flag==1)
						 { 
						  //父进程数数完成 
						  kill(pid,SIGUSR1);
						  flag=0; //标志已经给子进程发送完信号 
						  } 
				 } 
			 }else	if(pid==0)
				 { 
						 n=2;
						act.sa_handler	=	do_sig_child; 
						 sigemptyset(&act.sa_mask); 
						 act.sa_flags=0; 
						 sigaction(SIGUSR1,&act,NULL);
						while(1)
						{ 
							/*waitingforasignal*/;
							 if	(flag==1)	{
								kill(getppid(),SIGUSR2); flag=0; 
								 } 
							}
						}
	return0; 
}

示例中,通过 flag 变量标记程序实行进度。flag 置 1 表示数数完成。flag 置 0 表示给对方发送信号完成。 问题出现的位置,在父子进程 kill 函数之后需要紧接着调用 flag,将其置 0,标记信号已经发送。但,在这期 间很有可能被 kernel 调度,失去执行权利,而对方获取了执行时间,通过发送信号回调捕捉函数,从而修改了全局 的 flag。
如何解决该问题呢?可以使用后续课程讲到的“锁”机制。当操作全局变量的时候,通过加锁、解锁来解决该 问题。
现阶段,我们在编程期间如若使用全局变量,应在主观上注意全局变量的异步 IO 可能造成的问题。
有两个进程对同一个变量进行操作。

可/不可重入函数

一个函数在被调用执行期间(尚未调用结束),由于某种时序又被重复调用,称之为“重入”。根据函数实现的方 法可分为“可重入函数”和“不可重入函数”两种

例如:
在这里插入图片描述

显然,insert 函数是不可重入函数,重入调用,会导致意外结果呈现。究其原因,是该函数内部实现使用了全 局变量

注意事项

  1. 定义可重入函数,函数内不能含有全局变量及 static 变量,不能使用 malloc、free
  2. 信号捕捉函数应设计为可重入函数
  3. 信号处理程序可以调用的可重入函数可参阅 man7signal
  4. 没有包含在上述列表中的函数大多是不可重入的,其原因为:
    a) 使用静态数据结构
    b) 调用了 malloc 或 free
    c) 是标准 I/O 函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值