了解C语言代码段的预期行为

时间:2019-03-03 16:47:13

标签: c fork

我获得了c语言代码

#include <stdio.h> 
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define MAX_BUFFER 256
#define QUIT_STRING "q"

int makeargv(const char *s, const char *delimiters, char ***argvp);

int main (void) {
   char **chargv;
   char inbuf[MAX_BUFFER];

   for( ; ; ) {
      gets(inbuf);
      if (strcmp(inbuf, QUIT_STRING) == 0)
         return 0;
      if ((fork() == 0) && (makeargv(inbuf, " ", &chargv) > 0))
         execvp(chargv[0], chargv);
      wait(NULL);
   }
}

makeargv函数,用于从作为第一个参数传递的字符串中使用令牌(使用在第二个参数中传递的定界符),并将这些令牌存储在第三个参数所指向的数组中。

#include <errno.h>
#include <stdlib.h>
#include <string.h>

int makeargv(const char *s, const char *delimiters, char ***argvp) {
   int error;
   int i;
   int numtokens;
   const char *snew;
   char *t;

   if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
      errno = EINVAL;
      return -1;
   }
   *argvp = NULL;                           
   snew = s + strspn(s, delimiters);         /* snew is real start of string */
   if ((t = malloc(strlen(snew) + 1)) == NULL) 
      return -1; 
   strcpy(t, snew);               
   numtokens = 0;
   if (strtok(t, delimiters) != NULL)     /* count the number of tokens in s */
      for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ; 

                             /* create argument array for ptrs to the tokens */
   if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
      error = errno;
      free(t);
      errno = error;
      return -1; 
   } 
                        /* insert pointers to tokens into the argument array */
   if (numtokens == 0) 
      free(t);
   else {
      strcpy(t, snew);
      **argvp = strtok(t, delimiters);
      for (i = 1; i < numtokens; i++)
          *((*argvp) + i) = strtok(NULL, delimiters);
    } 
    *((*argvp) + numtokens) = NULL;             /* put in final NULL pointer */
    return numtokens;
}    

我需要回答以下三个问题

  1. 当用户给出无效命令(即,不存在可执行文件的命令)时,上述代码中实现的外壳将如何工作?

  2. 如果用户给出多个无效命令会怎样?

  3. 当用户在给出多个无效命令后尝试退出外壳时会发生什么情况。

这就是我对这些问题的回答

  1. execv将返回一个错误,但我认为它不会破坏代码,因此会导致两个派生尝试读取输入

  2. 将创建更多分叉

  3. 只有一个叉子会退出

问题

所有答案都正确吗?是否可以改善任何答案?

1 个答案:

答案 0 :(得分:1)

从来没有两个进程试图一次读取stdin。竞争条件使最终的环境无法使用。

 if (fork() ==0){ 
        if(...)
            execvp();
         _exit(255); /* don't fall back to parent code */
 }