2013-12-20 30 views
0

将大量数据快速写入C子进程时,出现Broken Pipe错误。Python中的C子进程:sub.stdin.write IOError中断管道

process = subprocess.Popen("./gpiopwm", stdin=subprocess.PIPE) 
while True: 
    process.stdin.write("m2000\n") 
    print "bytes written" 

gpiopwm.c的主回路的Sectio:

所以我从一个Python脚本运行AC子

printf("1\n"); 
while (1) { 
    fgets(input,7,stdin); // Takes input from python script 
    printf("2\n"); 

    numbers = input+1;  // stores all but first char of input 
    char first = input[0]; // stores first char of input 

    if (first=='m') { 
     printf("3\n"); 
     printf("%s\n",numbers); 
    } 
} 

然而,从这个输出如下:

1 
bytes written 
Traceback (most recent call last): 
    File "serial-receive-to-pwm.py", line 20, in <module> 
    process.stdin.write("m2000\n") 
IOError: [Errno 32] Broken pipe 

该C程序明显突破fgets行,如2从不打印。 我做错了什么?我怎样才能避免这种情况?

编辑: 我已更新fgets行,以便它不包括取消引用参数,但仍然收到损坏的管道错误。

编辑:如果您尝试从控制台上运行你的C程序 input被初始化为char *input="m2000";

+1

请显示'input'的完整声明(以及可能的初始化)。 –

回答

2

,你会看到它崩溃。如果你在一个调试器中运行,你会看到它在这条线:

fgets(*input,7,stdin); 

好像input是一个字符数组,当你取消对它的引用与*input你逝去的不是指针,但单char值。这导致未定义的行为和崩溃。

如果不是错误,那么该行应该给出您编译器提供的非常大的警告消息。不要忽视警告信息,它们通常是你做错事情并且可能危险的指标。


一般提示:当开发一个应该从另一程序调用,就像你在这里做节目,测试程序首先要确保它的工作原理。如果它不起作用,请先修复它。

最后提示:请记住,fgets包括目标字符串中的换行符。您可能需要检查它并将其删除。


有了上次的编辑,显示input声明,我们知道真正问题:您正在试图修改常量数据,并要写入超出数据的边界为好。

当你input指向一个字符串,你要记住,所有的文本字符串只读,你不能修改文本字符串。试图这样做是未定义的行为。更糟的是,你的字符串只有六个字符长,但你试着写七个字符。

第一变化的input的声明和初始化:

char input[16] = "m2000\n"; 

这将声明为阵列,位于所述叠层上,并且可以被修改。然后做

while (fgets(input, sizeof(input), stdin) != NULL) { ... } 

这完成两件事情:一是通过sizeof(input)的大小,你可以肯定的是fgets永远不会写出界。其次,通过在循环条件中使用fgets调用,循环将在Python脚本中断时结束,并且不会循环永远无法读取任何内容,然后处理您从未读过的数据。

+1

这不是很好吗()**还**明确告诉OP **如何**解决这个问题? ;-) – alk

+0

我已经说过错误在fgets行。编译器工作正常,否则它不会编译。 – theoB610

+0

@ theoB610:假设'char输入[至少7];'在此期间试试这个:'fgets(input,7,stdin);' – alk