Я запускаю некоторый код на Mac OSX 10.6.6 и XCode 3.2.4, и у меня есть довольно стандартный код: fork(), если pid == 0, то execvp с командой и аргументами (аргументы включают команду как первый элемент в массиве, и массив завершается нулем).
Мы рассмотрим это на моем занятии по операционным системам, и наша задача — написать простую оболочку. Запускайте команды с их аргументами и переключателями, как с перенаправлением (‹ и >), так и с каналом (|). У меня возникает несколько проблем.
1) Иногда я получаю сигнал EXC_SOFTWARE во время отладки (до сих пор я не получил его, если запускаю приложение вне XCode, но я новичок в Mac и не знал бы, как это будет выглядеть, если бы я это сделал)
2) Иногда getline для следующей команды получает мусор, который, кажется, печатается другими couts. Это начинает бесконечно зацикливаться, экспоненциально ломаясь. Я тестировал печать getpid() с каждым приглашением, и только начальный процесс распечатывает их, похоже, у меня нет случайной «форк-бомбы».
Вот что у меня есть до сих пор:
#include <iostream>
#include <string>
#include <unistd.h>
using namespace std;
char** Split(char* buffer, int &count) {
count = 1;
for (int i = 0; i < strlen(buffer); i++) {
if (buffer[i] == ' ') {
count++;
}
}
const char* delim = " ";
char* t = strtok(buffer, delim);
char** args = new char*[count + 1];
for (int i = 0; i < count; i++) {
args[i] = t;
t = strtok(NULL, delim);
}
args[count] = 0;
return args;
}
void Run(char** argv, int argc) {
int pid = 0;
if ((pid = fork()) == 0) {
//for testing purposes, print all of argv
for (int i = 0; i < argc; i++) {
cout << "{" << argv[i] << "}" << endl;
}
execvp(argv[0], argv);
cout << "ERROR 1" << endl;
exit(1);
} else if (pid < 0) {
cout << "ERROR 2" << endl;
exit(2);
}
wait(NULL);
}
int main(int argc, char * const argv[]) {
char buffer[512];
char prompt[] = ":> ";
int count = 0;
while (true) {
cout << prompt;
cin.getline(buffer, 512);
char **split = Split(buffer, count);
Run(split, count);
}
}
Это именно то, что у меня есть, вы должны уметь вырезать, вставлять и строить.
Я не силен в C++, и, скорее всего, произойдет утечка памяти, если я не удалю split
, но основное внимание я уделяю сигналу EXC_SOFTWARE и смотрю, что я делаю неправильно с проблемой зацикливания. Есть предположения?
РЕДАКТИРОВАТЬ:
Назначение требует очень ограниченной проверки ошибок, и я предполагаю, что все входные данные верны. Под правильным я подразумеваю правильно отформатированный и ограниченный для моего приложения запуск команды, то есть без странного подсчета пространства, без & для запуска асинхронного режима, без команд с несколькими конвейерами и т. д.