1

子プロセスの実行が終了したら、子プロセスの戻りステータスを出力したいと思います。

system()コードは、基本的にを使用して呼び出しを模倣できるようにすることexecl()です。

私の問題はprintf("The exit status of the process is : %d",status);、メイン関数の行が実行されないことです。これが原因で5秒間待機し、実行するsleep(5)と常に"Alarm clock"端末に出力されます。代わりに、システム関数から返される子の終了ステータスを返すようにします。

私はここで何か間違ったことをしていますか?

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<signal.h>
using namespace std;

void wakeup() {};

int sleep(int timer)
{
    struct sigaction action;
    //action.sa_handler = wakeup;
    action.sa_flags=0;
    sigemptyset(&action.sa_mask);

    if (sigaction(SIGALRM, &action, 0)==-1)
    {
        perror("sigaction");
        return -1;
    }
    (void)alarm(timer);
    (void)pause();
    return 0;
}

int system(const char *cmd)
{
        pid_t pid;
        int status;
        pid = fork();
        if (pid==0) //child
        {
            execl("/bin/sh","sh","-c",cmd,0);
            perror("execl");
            exit(errno);
        }
        /*if(sleep(5)==-1)
        {
            perror("sigaction");
        }*/
        sleep(5);
        if(waitpid(pid,&status,0)==pid && WIFEXITED(status))
            return WEXITSTATUS(status);


        return -1;
}
int main(int argc,char *argv[])
{
        int status;
        if(argc!=2)
        {
          cout<<"Usage Error\nCorrect usage:./a.out <cmd>\n";
          exit(0);
        }
        else
        {
            status=system(argv[1]);
            if(status!=0)
            {
                cout<<"The exit status of the process is : %d"<<status;
            }
        }
        return 0;
}

解決策: この課題を完了するのを手伝ってくれたDaveSに感謝します。

元の割り当ての質問は次のとおりです。 Write a program which should accept one command(like date/time/find..or any user created executable file) and run it by its child process, if the child process takes more than five seconds to run the command,parent should terminate the child process, else if the child terminates before 5 seconds-print exit status of the child.

完成したコード:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<signal.h>
using namespace std;
bool timeup=false;
void wakeup(int signum) {
    if(signum==SIGALRM)
    {
        timeup=true;
    }
};

int sleeper(int timer)
{
    struct sigaction action;
    action.sa_handler = wakeup;
    action.sa_flags=0;
    sigemptyset(&action.sa_mask);

    if (sigaction(SIGALRM, &action, 0)==-1)
    {
        perror("sigaction");
        return -1;
    }
    (void)alarm(timer);
    //(void)pause();
    return 0;
}

int system(pid_t *pid,const char *cmd)
{

        int status;
        *pid = fork();
        if (*pid==0)    //child
        {
        sleep(6); // remove or modify value to change how long the process will minimally take to execute
            execl("/bin/sh","sh","-c",cmd,0);
            perror("execl");
            exit(errno);
        }

        return 0;
}
int main(int argc,char *argv[])
{
        int status=-999;
    pid_t pid;
        if(argc!=2)
        {
          cout<<"Usage Error\nCorrect usage:./a.out <cmd>\n";
          exit(0);
        }
        else
        {

        system(&pid,argv[1]);

        sleeper(5);// the timer for 5 seconds

        if(waitpid(pid,&status,0)==pid && WIFEXITED(status))
                status = WEXITSTATUS(status);
        if(!timeup)
                cout<<"The exit status of the process is :"<<status<<"\n";
        else
        {
        cout<<"Took more that 5 seconds..Stopping\n";
        kill(pid, SIGTERM);
        //exit(0);
        }

        }
        return 0;
}
4

1 に答える 1

1

まず、あなたの目標が模倣することでもない限りsleep()、私はあなた自身を書く代わりにそれを使うでしょう。

sa_handlerとはいえ、sigaction構造のフィールドを初期化しているわけではありません。そのため、デフォルトのアクションを実行していると確信しています。SIGALRMのデフォルトのアクションは、プロセスを強制終了することです。

コメントアウトしたように、整数を受け入れるように関数を変更し、wakeup()それを使用してsa_handlerフィールドを初期化します。

于 2012-05-14T18:09:34.030 に答える