我正在学习C ++ [Java背景fwiw]并尝试将UNIX shell编写为项目。我正在遇到一个有趣的小问题,将输入标记为执行。 tok函数被调用两次,我不知道为什么。我目前的测试代码如下:
#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;
}
我实际运行程序时的输出是:
$ ./a.out
shell>> ls -l
0: ls
1: -l
done tokenizing...
0: ls
1: -l
done tokenizing...
我不确定为什么会这样做。任何人都可以指导我正确的方向吗?谢谢
答案 0 :(得分:9)
fork
函数返回两次,一次在原始进程中,一次在新创建的forked进程中。然后,这两个流程都会调用tok
。
似乎没有任何明确的原因可以调用fork
。因此,修复可能就像取消对fork
的调用一样简单。
答案 1 :(得分:1)
以下代码可以正常工作
#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;
}
答案 2 :(得分:1)
当您致电fork
时,您会创建两个流程。除了您收到的相应pid_t
之外,每个进程几乎都具有完全相同的状态。如果该值大于0,那么您在父进程(main)中,否则您在子进程中(或fork失败)。
如果不对返回的pid_t
执行检查,则两个进程都会调用tok
,从而导致您目击的双重呼叫行为。
隐藏pid
支票后的电话,如下所示:
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);
}
要查看父母和子进程的共同点(或不是):检查docs