System函数与脚本的后台执行

本文通过一个具体的故障报告介绍了Linux系统中System函数如何调用后台执行脚本的问题。System函数会创建子进程执行命令,而不会等待脚本执行完毕即返回,这可能导致并发问题。文中还探讨了fork()函数的工作原理以及system()源码解析。

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

    昨天BSC测试组开了一个U0的Fault Report.
    后来发现问题了:正常情况下当我们的CCP板插入机架后,本来OMCP板应该先配置其dhcp,然后restart dhcp,这样CCP板才能正常工作。但是现在看到的情况是,在dhcp配置完成之前,OMCP上的dhcp server就被restart了。细读trace和代码,最终发现了问题所在---->System函数调用后台执行的脚本。
    先介绍一下System函数,在linux中man system得到的解释是:
system()  executes  a command specified in string by calling /bin/sh -c string, and returns after the command has been completed.  During  execution  of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
system() 以字符串为参数,该字符串是一个shell命令或者shell脚本。shell命令或脚本返回后,system()才返回,在此过程中SIGCHLD会被阻塞,SIGINT和SIGQUIT会被忽略。
    再回到前面我说的问题,在我的程序中:
int rc;
rc 
= system(/usr/local/bin/build_dhcp.sh &");   // (1)
......
rc 
= system("/etc/init.d/dhcpd restart");  // (2)
    根据man system得到的信息,从字面上看,容易让人(比如我T_T)产生误会,以为(1)处的脚本完全执行完,dhcp配置好了,(1)处的system函数才会返回,接下来再执行(2)处的命令来restart dhcp。事实上,并非如此,(1)处的system函数调用shell脚本,该脚本转为后台执行,此时system函数就返回了,接下来(2)的system函数就开始执行了。由于build_dhcp.sh执行时间较长,因此,当dhcp还没有配置好的时候,dhcp server restart,最终导致插进去的这个CCP板无法正常工作。
    工作的问题解决了,大快人心。顺便也就进一步了解一下system函数吧。
    Linux中system()源码如下:
    解释一下,当命令参数为NULL时直接返回,否则fork出一个子进程。
    顺便说一下fork(),假如在进程A调用fork(),内核就创建一个新的进程B,并将A的内存映像复制到B的进程空间中。因此,进程A和进程B一模一样,只有根据fork()的返回值就才能知道谁是父进程,谁是子进程。fork在子进程中返回0,在父进程中返回子进程的pid。
    在system()的源代码中,父进程使用waitpid等待子进程结束,子进程则是通过调用execl("/bin/sh", "sh", "-c", cmdstring, (char*)0)调用shell,这个shell的路径是/bin/sh,然后子进程就变成了一个shell进程,这个shell的参数就是system接受的参数,在windows中的shell是command。
#include <sys/types.h>
#include 
<sys/wait.h>
#include 
<errno.h>
#include 
<unistd.h>

int system(const char * cmdstring)
{
    pid_t pid;
    
int status;

    
if(cmdstring == NULL){
        
return (1);
    }


    
if((pid = fork())<0){
        status 
= -1;
    }

    
else if(pid == 0)//子进中运行脚本命令
        execl(
"/bin/sh""sh""-c", cmdstring, (char *)0);
        
-exit(127); //子进程正常执行则不会执行此语句
    }

    
else//父进程中等待子进程返回
            
while(waitpid(pid, &status, 0< 0){
                
if(errno != EINTER){
                    status 
= -1;
                    
break;
                }

            }

    }

    
return status;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值