关于shell:C ++函数运行两次但只调用一次

C++ function running twice but only called once

我正在学习C++(Java背景FWIW),并尝试编写UNIX外壳作为一个项目。我遇到了一个有趣的小问题,就是如何标记输入以便执行。tok函数被调用了两次,我不知道为什么。我当前的测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <vector>
#include <sstream>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>

using namespace std;

void tok(string, char**);

int main(){
    const char* EXIT ="exit";

    string input;

    cout <<"shell>>";
    getline(cin, input);

    pid_t pid = fork();

    char* args[64]; //arbitrary size, 64 possible whitespace-delimited tokens in command
    tok(input, args);
    return 0;
  }

  //copied from http://stackoverflow.com/questions/14265581/parse-split-a-string-in-c-using-string-delimiter-standard-c
void tok(string inStr, char** args){
    int last = 0, next = 0, i = 0;
    while( (next = inStr.find(' ', last)) != -1){
        cout << i++ <<":" <<  inStr.substr(last, next-last) << endl;
        *args++ = strdup(inStr.substr(last, next-last).c_str());
        last = next + 1;
    }
    cout << i++ <<":" << inStr.substr(last) << endl;
    *args++ = strdup(inStr.substr(last).c_str());
    *args = '\0';
    cout <<"done tokenizing..." << endl;
}

我实际运行程序时的输出是:

1
2
3
4
5
6
7
8
$ ./a.out
shell>> ls -l
0: ls
1: -l
done tokenizing...
0: ls
1: -l
done tokenizing...

我不知道为什么会这样。有人能给我指路吗?谢谢你


fork函数返回两次,一次在原始进程中,一次在新创建的分叉进程中。这两个过程都称为tok

你为什么叫fork,似乎没有任何明确的理由。因此,修复可能与消除对fork的调用一样简单。


当您调用fork时,将创建两个进程。每个进程的状态几乎完全相同,除了您收到的各自的pid_t。如果该值大于0,则表示您在父进程(主进程)中,否则表示您在子进程中(或fork失败)。

如果不对返回的pid_t执行检查,两个进程都将调用tok,从而导致您看到的双重调用行为。

将呼叫隐藏在对pid的支票后面,如下所示:

1
2
3
4
5
6
pid_t pid = fork();
if (pid > 0) // have parent process call tok
{
   char* args[64]; //arbitrary size, 64 possible whitespace-delimited tokens in command
   tok(input, args);
}

查看父进程和子进程还有哪些共同点(或不相同):检查文档


以下代码可以正常工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <vector>
#include <sstream>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>

using namespace std;

void tok(string, char**);

int main(){
const char* EXIT ="exit";

 string input;

 cout <<"shell>>";
 getline(cin, input);

// pid_t pid = fork();

 char* args[64];
 tok(input, args);
 return 0;
}


void tok(string inStr, char** args){
int last = 0, next = 0, i = 0;
while( (next = inStr.find(' ', last)) != -1){
    cout << i++ <<":" <<  inStr.substr(last, next-last) << endl;
    *args++ = strdup(inStr.substr(last, next-last).c_str());
    last = next + 1;
}
cout << i++ <<":" << inStr.substr(last) << endl;
*args++ = strdup(inStr.substr(last).c_str());
*args = '\0';
cout <<"done tokenizing..." << endl;
}