我想编写一个程序来创建一个新进程,在该子进程中,它应该执行命令:ls
。同时,父母应该等待孩子死亡。但是,我的代码不起作用。
请帮助我,非常感谢你!
int main()
{
char * read;
size_t size;
getline(&read , &size , stdin);
read[strlen(read)-1] = '\0';
printf("%s\n" , read);
int status;
pid_t f;
if((f = fork()) == 0)
{
execvp(read , &read);
exit(0);
}
else
{
wait(&status);
}
}
答案 0 :(得分:3)
来自man execvp:
execv(),execvp()和execvpe()函数提供了一个指向以null结尾的字符串的指针数组,这些字符串表示新程序可用的参数列表。按照惯例,第一个参数应指向与正在执行的文件关联的文件名。 指针数组必须以NULL指针终止。
您需要使用char*
数组,并将最后一个元素设置为NULL
。
我不确定getline()
正在阅读什么,但我想这是ls
d的目录。 execvp()
的第一个参数应为ls
,第二个参数为char*
的数组。
答案 1 :(得分:1)
请考虑以下事项:
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[])
{
char *input_arg[2];
char *input_str = NULL;
size_t input_len = 0;
char **args;
ssize_t len;
size_t n;
pid_t child, p;
int status;
if (argc < 2) {
/* No command line parameters. Read command from stdin. */
len = getline(&input_str, &input_len, stdin);
/* Find length excluding the newline at end. */
if (len > (ssize_t)0)
n = strcspn(input_str, "\r\n");
else
n = 0;
if (n > (size_t)0) {
/* Terminate input command before the newline. */
input_str[n] = '\0';
} else {
fprintf(stderr, "No input, no command.\n");
return 1;
}
input_arg[0] = input_str;
input_arg[1] = NULL;
args = input_arg;
} else {
/* Use command line parameters */
argv[argc] = NULL;
args = argv + 1;
}
child = fork();
if (child == (pid_t)-1) {
fprintf(stderr, "Cannot fork: %s.\n", strerror(errno));
return 1;
}
if (!child) {
/* This is the child process. */
errno = ENOENT;
execvp(args[0], args);
fprintf(stderr, "%s: %s.\n", args[0], strerror(errno));
exit(127);
}
do {
p = waitpid(child, &status, 0);
} while (p == (pid_t)-1 && errno == EINTR);
if (p == (pid_t)-1) {
fprintf(stderr, "Lost child process: %s.\n", strerror(errno));
return 127;
}
if (p != child) {
fprintf(stderr, "waitpid() library bug occurred.\n");
return 127;
}
if (WIFEXITED(status)) {
if (!WEXITSTATUS(status))
fprintf(stderr, "Command successful.\n");
else
fprintf(stderr, "Command failed with exit status %d.\n", WEXITSTATUS(status));
return WEXITSTATUS(status);
}
if (WIFSIGNALED(status)) {
fprintf(stderr, "Command died by signal %s.\n", strsignal(WTERMSIG(status)));
return 126;
}
fprintf(stderr, "Command died from unknown causes.\n");
return 125;
}
如果指定,上面使用命令行参数,否则它从标准输入中读取一个。由于标准输入未标记化,因此您只能提供命令名称,不能提供参数。如果将input_arg[]
数组放大为
char *input_arg[4];
并将作业修改为
input_arg[0] = "/bin/sh";
input_arg[1] = "-c";
input_arg[2] = input_str;
input_arg[3] = NULL;
args = input_arg;
然后输入字符串将使用/bin/sh
shell进行处理,就像popen()
一样。
您还可以使用len = getdelim(&input_str, &input_len, '\0', stdin);
并移除input_str[n] = '\0';
分配以允许多行输入; shell应该处理那些罚款,只要它足够短以适应命令行参数缓冲区(最大长度取决于你的操作系统)。
shell如何将输入拆分为单独的命令和参数的规则相当复杂,您不应该尝试模拟它们。相反,找一个简单的方法让用户单独指定参数(比如命令行参数case),或者使用shell为你做。如果不进行任何拆分,则可能需要删除输入行末尾的换行符。
需要注意的是,对于execvp(file, args)
,args[0]
是应用看到的名称($0
或argv[0]
),而args[1]
是第一个参数。每个参数都由NUL(\0
)终止,就像字符串通常在C中一样,args
指针数组必须以NULL
指针结束。如果没有参数,则为args[1] == NULL
。
答案 2 :(得分:0)
为什么不使用系统命令......
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int i;
printf ("Executing command ls...\n");
i=system ("ls");
printf ("The value returned was: %d.\n",i);
return 0;
}
更新
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void main(void)
{
pid_t pid;
pid = fork();
if (pid == 0) // this is child process
{
int i;
printf ("Executing command ls...\n");
i=system ("ls");
printf ("The value returned was: %d.\n",i);
}
else // this is paraent process
{
int status=0
wait(&status);
printf ("Child process is returned with: %d.\n",status);
}
}