如何通过C中的命令行参数传递管道和其他值?
我试图创建几个程序,其中第一个程序启动所有必需的IPC元素。我遇到的问题是使用第一个值执行子程序。我曾尝试以下:如何通过C中的命令行参数传递管道和其他值?
int sem_id = semget (key1, 4, IPC_CREAT | 0666);
int shmid = shmget(key2, 1024, 0644 | IPC_CREAT);
int pipe1[2];
if (pipe (pipe1)){
printf("Error: %s",strerror(errno));
exit(1);
}
if(execl("/home/tropix/program-3","/home/tropix/program-3", sem_id, shmid, pipe1, (char*)0) == 0){
fprintf(stderr, "File Execution of program 3 failed.\n");
exit(1);
}
计划3没有执行,所以我显然有我的EXECL语句的问题。如果我删除它运行的变量sem_id,shmid和pipe2。
感谢您的任何建议。
编辑:添加用于创建shmid和sem_id的语句。我可以将这些int打印到标准输出,所以我相信他们有价值。而据了解程序3是否正在执行,见方案3:
main(int argc, char *argv[]){
int x;
printf("Number of args = %d", argc);
for(x=0;x<argc;x++){
printf("arg#: %d, %s\n",x,argv[x]);
}
}
另注:我已编译的程序3.如果我删除了execl的参数与引用的话取代他们(“测试”),他们在子页面中显示为参数。但在这种情况下,NOTHING正在从程序3打印。
程序的参数都必须是字符串。
因此,要将信号标识,共享内存标识和文件描述符传递给执行的程序,需要调用程序代码将数字转换为字符串,并将执行的程序将字符串转换回数字,然后适当使用。
你的代码不会显示'pipe2'...我认为这是一个简单的int
,但是如果它是一个数组(如pipe1
是),那么你需要用0或1来下标相关文件描述符:
char shmarg[20];
char semarg[20];
char piparg[20];
int semid = semget (key1, 4, IPC_CREAT | 0666);
int shmid = shmget(key2, 1024, 0644 | IPC_CREAT);
int pipe1[2];
const char *cmd = "/home/tropix/program-3";
if (pipe(pipe1))
{
printf("Failed to create pipe: %s\n", strerror(errno));
exit(1);
}
snprintf(shmarg, sizeof(shmarg), "%d", shmid);
snprintf(semarg, sizeof(semarg), "%d", semid);
snprintf(piparg, sizeof(piparg), "%d", pipe2);
execl(cmd, cmd, semarg, shmarg, piparg, (char*)0);
fprintf(stderr, "File Execution of program 3 failed.\n");
exit(1);
不清楚为什么你创建了pipe1
;你需要做适当的管道工作。如果execl()
返回,则失败。你不需要测试它的返回值。
从评论:
[我]刚切割出的相关章节简单[...] [我]不知道你的意思,“适当的管道是什么“用pipe1?你能告诉我应该怎么做,或者向我介绍一些关于如何初始化管道并将它传递给下一个文件的信息?我意识到在程序中创建管道需要它可能是一个更好的选择,但在这种情况下,在程序1中初始化管道是必需的。
简单的问题是一个好主意......
我假设在拨打pipe()
和execl()
之间,有一个fork()
被省略。否则,pipe()
是毫无意义的。
据推测,创造了管道的目的是让孩子过程中的谈话给父母,或父进程交谈的孩子。有双向管道,但它们既不标准也不便携;因此,我认为你有一个常规的单向管道。既然你是路过的文件描述符作为参数传递给孩子,我们不是重定向标准输入或标准输出的孩子 - 这就是你经常(但不总是)做一个管道。
因此,修改后的代码可能是(删除空行,以避免滚动条):
char shmarg[20];
char semarg[20];
char piparg[20];
int semid = semget(key1, 4, IPC_CREAT | 0666);
int shmid = shmget(key2, 1024, 0644 | IPC_CREAT);
int pipe1[2];
const char *cmd = "/home/tropix/program-3";
if (pipe(pipe1))
{
printf("Failed to create pipe: %s\n", strerror(errno));
exit(1);
}
pid_t pid = fork();
if (pid < 0)
err_exit("Failed to fork");
else if (pid > 0)
{
/* Do parental things */
close(pipe1[0]);
...write to pipe1[1]...
}
else
{
/* Do childish things */
/* Assuming child is reading from pipe */
close(pipe1[1]);
snprintf(shmarg, sizeof(shmarg), "%d", shmid);
snprintf(semarg, sizeof(semarg), "%d", semid);
snprintf(piparg, sizeof(piparg), "%d", pipe1[0]);
execl(cmd, cmd, semarg, shmarg, piparg, (char*)0);
fprintf(stderr, "File Execution of program 3 failed.\n");
exit(1);
}
显然,如果管由父读取和孩子写的,你需要玩弄关闭和指定的文件描述符号码。
几乎总是,你最终收盘从pipe()
返回两个文件描述符的至少一个。如果重定向管道标准输入或标准输出,您通常使用dup2()
复制管道的适当结束,然后关闭从pipe()
返回两个文件描述符。由于所有这些都与管道混淆,所以俗称管道。
你怎么知道program-3
没有运行?如果/home/tropix/program-3
是可执行程序,则execl
调用看起来没问题。您能提供关于sem_id
,shmid
和pipe2
的定义吗?
所有代码管道旨在为PIPE1,我只是切割出的相关章节简单,所以请原谅他的错误。但你的答案是完全合理的,但我不确定你对管道1的“适当管道”是什么意思?你能告诉我应该怎么做,或者向我介绍一些关于如何初始化管道并将它传递给下一个文件的信息?我意识到在程序中创建管道需要它可能是一个更好的选择,但在这种情况下,在程序1中初始化管道是必需的。非常感谢输入,顺便说一句 – Josh 2011-05-08 16:40:51
尝试了几件事后,我明白了。谢谢你的时间! – Josh 2011-05-08 16:49:51