在下面的代码中,我希望能够使用以换行符分隔的 stdin bash 命令进行输入,并使用 forks 和 execvp 顺序执行它们。现在,我的代码获取该行,对其进行标记(为了论证),然后将其附加到名为 cmd 的 char* 数组。然后我想将其作为一行添加到 cmdList 中。然而,每次我尝试使用 memcpy 时,它都不会输出我预期的行为,我希望有人可以帮助解释并为我指出正确的方向,谢谢。完整的代码库如下。目前,我正在使用 ./sequence < cmdfile 进行测试,其中命令文件包含这些行。sequence.c 当前仅输出日期。
cmd文件
whoami
cal 4 2020
echo The time is:
date
序列.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sysexits.h>
#define MAX_ARGS 10
#define MAX_LINE 256
#define MAX_COMMANDS 100
int main() {
int cmdSize;
char line[MAX_LINE];
char* cmdList[MAX_COMMANDS][MAX_ARGS + 1];
//read 100 lines
for(int i = 0; i < MAX_COMMANDS; i++) {
cmdSize = 0; //reset cmdSize every iter
fgets(line, MAX_LINE, stdin); //read line from stdin
if(line[0] == 10) {
break;
}
line[strcspn(line,"\n")] = 0; //strip \n from back of lines so that the commands are clean
char* token = strtok(line, " ");
char* cmd[11] = {};
while(token) {
cmd[cmdSize] = token;
//cmdList[i][cmdSize] = token;
cmdSize++;
token = strtok(NULL, " ");
}//tokenise and add to cmd arr
memcpy(cmdList[i], cmd, sizeof(cmd));
}
printf("%s, ", cmdList[0][0]);
printf("%s, ", cmdList[1][0]);
printf("%s, ", cmdList[2][0]);
//start of forks, broken right now
for (int i = 0; i<cmdSize; i++) {
//forks
int fid;
fid = fork();
if (fid < 0) {
perror("fork error");
exit(EXIT_FAILURE);
}
else if (fid == 0) {
execvp(cmdList[i][0], cmdList[i]); //execute on child
perror("Exec error");
exit(EXIT_FAILURE);
return 0;
}
else {
wait(NULL); // wait until child is finished
}
}
return 0;
}
尝试使用循环附加到二维数组,但不起作用,行为相同
问题是所有对 的调用
strtok
将始终为您提供指向单个line
数组的指针。外
for
循环的每次迭代都会“重置”数组的内容line
,因此您存储的所有指针cmdList
都将指向line
数组中的不同位置,这些位置始终包含上次成功调用的内容fgets
您需要实际复制字符串,而不是指针。或者使用例如动态分配
strdup
(或者如果您的系统没有的话您自己的实现)。是一个浅拷贝。它只复制指针,而不复制底层数据。您需要实际复制底层数据,否则最终会得到所有指向单个
line
数组内部的指针,该数组将包含最近fgets()
调用的内容。由于您已经假定 POSIX 支持,所以很简单:
另请注意
char* cmd[11] = {};
,除非您使用 GNU 扩展,否则它在 C2X 之前无效。不比较 ASCII 代码,而是使用实际字符: