Linux下系统调用execl会等待一段时间才执行指定的可执行程序,这是为什么?

时间:2022-07-07 08:36:53
程序编译运行环境:
Red Hat Enterprise Linux Server release 6.4 64bits

问题描述:
fork子进程后,使用execl或者execlp调用可执行程序会出现等待一段时间才进入可执行程序,为什么会出现等待,有猿友遇到这个问题吗?很是奇怪,并非每一次都会出现这样的问题,如果重启电脑后,就不会出现,但是运行一段时候后又会出现。

主要代码:
Result* ALGJob::computation(ComputationTask *task, OriginalTask *original_task) {
    CHECK_NOTNULL(task);
    CHECK_NOTNULL(original_task);
    ALGComputationTask *ALG_task = static_cast<ALGComputationTask*>(task);
    ALGOriginalTask *ALG_original_task = static_cast<ALGOriginalTask*>(original_task);
ALGResult* ALG_Result=new ALGResult;//用于接受子进程返回的计算结果
ALG_Result->init();
    cout<<endl<<"-----------------------------------------------------------start computation---------------------------------------------"<<endl;
    sighandler_t old_handler;
old_handler=signal(SIGCHLD,SIG_DFL);
string cacheStr = getCacheContext(task, original_task);
uint64 cache_len = cacheStr.length()+1;
cout << "compute node cache len " << cache_len << endl;
    pid_t pid;//子进程ID
    int shmid;//共享内存ID
    ALGOriginalTask* ALG_shm_addr=NULL;
ALGResult* ALG_Result_shm_addr=NULL;
char *share_cache = NULL;
void* shm_addr=NULL;//共享内存首地址
    if((shmid=shmget(IPC_PRIVATE,sizeof(ALGOriginalTask)+sizeof(ALGResult)+sizeof(char)*cache_len,IPC_CREAT|0640))<0)//创建当前进程的父子进程私有共享内存
{
      perror("shmget");
      exit(-1);
    } 
if((shm_addr=shmat(shmid,0,0))==(void*)-1) {
           perror("Parent:shmat");
           exit(-1);
    }
else
memset(shm_addr,NULL,sizeof(ALGOriginalTask)+sizeof(ALGResult)+sizeof(char)*cache_len); 
    switch(pid=fork())
{
  case -1:
    perror("fork");
exit(-1);
  case 0://child
  {
pid_t ppid=getppid();
pid_t childpid=getpid();
cout<<"in computation child process"<<endl;
cout<<"ppid:"<<ppid<<" pid:"<<childpid<<endl;
    //构造ALG.out参数
string shmId=itoa(shmid);
string plain_num=itoa(ALG_task->plain_num);
string plain_len=itoa(ALG_task->plain_len);
cout<<"in computation child plain_num:"<<plain_num<<endl;
cout<<"in computation child plain_len:"<<plain_len<<endl;

const char* argv[4]={"./ALG.out",shmId.c_str(),plain_num.c_str(),plain_len.c_str()};
cout<<"-----------------start the atomic charset computation-------------------"<<endl;
if(execl(argv[0], argv[0], argv[1], argv[2], argv[3], NULL)==-1)//会卡一段时间再进入ALG.out
perror("execl error!!!");
    cout<<"-----------------end the atomic charset computation-------------------"<<endl;
    exit(0);
  }
  default://parent
  {
cout<<"in computation parent process"<<endl;
cout<<"cpid:"<<pid<<endl;
//set share memory form 
ALG_shm_addr=static_cast<ALGOriginalTask*>(shm_addr);
pthread_mutex_init(&ALG_shm_addr->mutex,NULL); 
perror("init shm in parent");
pthread_mutex_lock(&ALG_shm_addr->mutex);
perror("lock shm in parent ");

//initialize originalTask
ALG_shm_addr->algorithm=ALG_original_task->algorithm;
ALG_shm_addr->encodeType=ALG_original_task->encodeType;
ALG_shm_addr->cipher_num=ALG_original_task->cipher_num;
ALG_shm_addr->cipher_len=ALG_original_task->cipher_len;
ALG_shm_addr->salt_len=ALG_original_task->salt_len;
//memcpy(ALG_shm_addr->task_name,ALG_original_task->task_name,20);
        memcpy(ALG_shm_addr->cipher,ALG_original_task->cipher,128*256);
memcpy(ALG_shm_addr->salt,ALG_original_task->salt,128*32);
    memcpy(ALG_shm_addr->re,ALG_original_task->re,32*256);

    void* cache_p = shm_addr + sizeof(ALGOriginalTask);
    share_cache = (char*)cache_p;
    memcpy(share_cache, cacheStr.c_str(), cache_len);

perror("in parent end write shm");
pthread_mutex_unlock(&ALG_shm_addr->mutex);
perror("in parent unlock");

int status;
//sighandler_t old_handler;
old_handler=signal(SIGCHLD,SIG_DFL);

cout << "computation parent wait child process" << endl;
//下面有可能会出错
int ret = waitpid(pid,&status,0);//waiting for the child process finish
cout << " wait pid return is " << ret << endl;
if (WCOREDUMP(status)) {
cout << "child core dump" << endl;
}
perror("in parent waitpid:");
signal(SIGCHLD,old_handler);

cout<<"child process exit normal with status: "<<status<<endl;
ALG_Result_shm_addr=static_cast<ALGResult*>(shm_addr);
//read the result form share memory
memcpy(&ALG_Result->ts,&ALG_Result_shm_addr->ts,sizeof(struct timeval));
memcpy(&ALG_Result->te,&ALG_Result_shm_addr->te,sizeof(struct timeval));

ALG_Result->success_num=ALG_Result_shm_addr->success_num;
memcpy(ALG_Result->ret_plain,ALG_Result_shm_addr->ret_plain,128*64);


//删除父进程的共享内存映射地址
        if (shmdt(shm_addr)<0) {
            perror("Parent:shmdt");
            exit(1);
        }
        if (shmctl(shmid,IPC_RMID,NULL)==-1)//delete the share memory
{
perror("shmct:IPC_RMID");
exit(-1);
        }
  }
}//end fork

ALG_Result->algorithm=ALG_original_task->algorithm;
memcpy(ALG_Result->cipher,ALG_original_task->cipher,128*256);
    memcpy(ALG_Result->salt,ALG_original_task->salt,128*32);
    ALG_Result->regulation_index = ALG_task->regulation_index;
    cout << "-----------------------------------------------end computation----------------------------------------------------- " << endl;
    return ALG_Result;
}

6 个解决方案

#1


重启电脑后,就不会出现,但是运行一段时候后又会出现

看起来 CPU 被占用了

#2


引用 1 楼 zhxianbin 的回复:
重启电脑后,就不会出现,但是运行一段时候后又会出现

看起来 CPU 被占用了


引用 1 楼 zhxianbin 的回复:
重启电脑后,就不会出现,但是运行一段时候后又会出现

看起来 CPU 被占用了

能具体说明内在的机制吗?那如何解决这个问题呢?我这个程序需要运行很长时间,长则几个月,服务器一般不能重启的,该如何解决呢?

#3


看看慢的时候,cpu的各个核是不是使用率都很高

#4


引用 3 楼 Arnold9009 的回复:
看看慢的时候,cpu的各个核是不是使用率都很高

下面这个截图是top命令显示的信息,此时execl卡住了,正在阻塞,但是cpu的使用率也没有很高吧?
Linux下系统调用execl会等待一段时间才执行指定的可执行程序,这是为什么?

#5


会不停的 fork -exec 吗?

#6


top的第一个进程? S状态应该是在等待什么事件吧?
可以看看wait在什么地方。估计跟IO有关系。

#1


重启电脑后,就不会出现,但是运行一段时候后又会出现

看起来 CPU 被占用了

#2


引用 1 楼 zhxianbin 的回复:
重启电脑后,就不会出现,但是运行一段时候后又会出现

看起来 CPU 被占用了


引用 1 楼 zhxianbin 的回复:
重启电脑后,就不会出现,但是运行一段时候后又会出现

看起来 CPU 被占用了

能具体说明内在的机制吗?那如何解决这个问题呢?我这个程序需要运行很长时间,长则几个月,服务器一般不能重启的,该如何解决呢?

#3


看看慢的时候,cpu的各个核是不是使用率都很高

#4


引用 3 楼 Arnold9009 的回复:
看看慢的时候,cpu的各个核是不是使用率都很高

下面这个截图是top命令显示的信息,此时execl卡住了,正在阻塞,但是cpu的使用率也没有很高吧?
Linux下系统调用execl会等待一段时间才执行指定的可执行程序,这是为什么?

#5


会不停的 fork -exec 吗?

#6


top的第一个进程? S状态应该是在等待什么事件吧?
可以看看wait在什么地方。估计跟IO有关系。