程序应该执行一些循环:
发出提示并阅读一行文字。
将该行分解为单词。
如果命令是内置命令,请自行处理,然后返回读取步骤。否则,
执行fork以创建新进程。报告任何失败的原因(当然,如果分支失败,请不要执行。)
子进程将列表中的第一个单词视为命令的名称,并使用exec调用运行它。将整个列表作为参数发送到程序。报告任何失败的原因。
父进程等待子进程退出,然后报告其状态。
返回读取下一个命令。
我在下面写下了头部,身体和实现
这是行解析类:
#include <string>
using namespace std;
/*
* This class takes a C++ string and provides an array of plain C strings
* (array of pointers to char) representing the words in the line.
*/
class LineBreaker {
public:
// Construct the object, providing the line of text to be
// broken up.
LineBreaker(const string &s);
// Clean up.
~LineBreaker() {
delete [] m_data;
delete [] m_parmlist;
}
// Return an pointer to the first slot of an array of pointers
// containing the words in the string sent to the constructor.
// The list is terminated with a NULL pointer.
char **parmlist() { return m_parmlist; }
private:
char *m_data; // Dyn array of characters from the string.
char **m_parmlist; // Array of words
};
这是跑步者计划,是身体:
/*
* Simple program to demonstrate the fork/exec/run sequence for creating
* processes in Unix.
*/
#include <iostream>
#include <string>
using namespace std;
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "linebreaker.h"
main()
{
/* Ask for a program to run. This is just the file name of an
executable. */
cout << "Your command? ";
string cmd;
getline(cin, cmd);
LineBreaker breaker(cmd);
/* Create a child process and try to run the program in it. */
if(fork() == 0) {
execv(breaker.parmlist()[0], breaker.parmlist());
cout << "Sorry, the exec failed." << endl;
exit(1);
}
/* See what was the cause of the child processes' demise. */
int status;
wait(&status); /*we only need to change this part, and use something like this if(string(breaker.parlist()[0]) == "exit") */
if(WIFEXITED(status)) cout << "Exited." << endl;
else if(WIFSIGNALED(status)) cout << "Killed." << endl;
else cout << "Mysteriously vanished." << endl;
}
/*
* Note: This program really should check the return values for fork() and for
* exec() to make sure they succeeded, and print an error message if not.
* Failure is indicated by a negative return value. It would also help to use
* errno and strerror() to print a descriptive error message in place of the
* existing exec() failure message, or for the new messages.
*
* It also uses uses gets() and fixed-size buffers, which creates a risk of
* buffer overflow.
*/
这是实施:
#include <string>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <list>
#include "linebreaker.h"
LineBreaker::LineBreaker(const string &s)
{
// Copy the string as a character array.
m_data = new char[s.length()+1];
strcpy(m_data, s.c_str());
// Find all the words.
char last = ' ';
list<char *> parts;
for(char *scan = m_data; *scan; ++scan) {
char curr = *scan;
if(isspace(last) && !isspace(curr))
parts.push_back(scan);
else if(!isspace(last) && isspace(curr))
*scan = '\0';
last = curr;
}
// Allocate the array of pointers for exec, and copy the
// pointer into it. Then add the NULL terminator.
m_parmlist = new char * [parts.size()+1];
copy(parts.begin(), parts.end(), m_parmlist);
m_parmlist[parts.size()] = NULL;
}
我想在while循环中包含现有运行程序的大部分代码,以便它会重复读取和执行命令,而不是读取并退出。
在跑步者程序中,输入空行会产生错误(执行失败)。更改程序,以便输入一个空行(没有单词,因此没有命令名称),不运行任何命令,但程序只返回提示然后读取另一个命令。
此版本在常用位置搜索命令文件,因此不必查找要执行的文件的完整路径。跑步者计划使用execv;只需用execvp替换。
检查每个fork,exec或wait调用的返回码以检查是否有失败。我想使用errno和strerror来打印一条消息,说明失败的原因。实现两个无法使用fork / exec运行的命令。这些是exit命令和cd命令。这些是shell必须自己执行的内置命令。对于状态报告,如果程序以0以外的代码(错误退出)退出,或者如果崩溃,则报告该情况。对于正常退出,什么都不说。报告退出代码或崩溃原因。更多内容如下。
答案 0 :(得分:0)
不是一个完整的答案,因为这是作业,但这里有一个提示:while (std::getline( std::cin, cmd ))
这是有效的,因为getline()
返回对输入流的引用,当您将其转换为bool
值时,它将返回true
,而流尚未遇到结束文件或错误。