C->;Shell—在读之前写入的块
我想把一个字符从c程序发送到shell程序。我使用命名管道发送字母“a”,无论何时需要。我只需要打开管道一次。下面是一个例子:C->;Shell—在读之前写入的块,c,shell,C,Shell,我想把一个字符从c程序发送到shell程序。我使用命名管道发送字母“a”,无论何时需要。我只需要打开管道一次。下面是一个例子: #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> int main(){ int fd; mkfifo("/tmp/test", 0666); fd = open("/tmp/test
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main(){
int fd;
mkfifo("/tmp/test", 0666);
fd = open("/tmp/test", O_WRONLY);
printf("Opened\n");
char * a = "a";
while(1){
printf("Writing to pipe...\n");
write(fd,a,1);
sleep(1);
}
}
问题是在一个头部之后,即使没有人,c也会源源不断地流入管道
我注意到open()会一直阻塞,直到有人在另一端。如何让write()在有人阅读之前阻止
我宁愿在write()上使用此功能,也不愿在read()上使用此功能,因为我认为在为每个请求打开文件时会有很多开销
谢谢
更新
这就是我在Java中处理它的方式,它会等到有人监听这个管道后再继续。也许只是因为它是一种更高级的语言
public static void writeToPipe(int val, String pipename){
try{
pipe_out = new PrintStream("/tmp/" + pipename);
}catch(Exception e){
System.out.println("Could not open a pipe for output!");
e.printStackTrace();
}
try{
pipe_out.println(val);
}catch(Exception e){
System.out.println("Could not write to pipe!");
e.printStackTrace();
}
try{
pipe_out.close();
}catch(Exception e){
System.out.println("Could not close the output pipe!");
e.printStackTrace();
}
}
更新#2-这是解决方案
这是我基于David的想法编写的代码,虽然很粗糙,但很有效。我不是检查命名管道是否存在,只是禁止它退出
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(int argc, char **argv){
mkfifo("/tmp/test", 0666);
while(1){
int fd, status;
if ((fd = open ("/tmp/test", O_WRONLY)) == -1) {
perror ("open failed");
return 1;
}
printf("Opened Pipe\n");
char a = 'a';
int f = fork();
if(f == -1){
perror("fork");
exit(1);
}else if(f == 0){
//This is by the child process
if (write (fd, &a, 1) == -1) {
close(fd);
perror ("open failed");
return 1;
}
}else{
//This is the parent process
int w = waitpid(f, &status, WUNTRACED | WCONTINUED);
if (w == -1){
perror("waitpid");
exit(EXIT_FAILURE);
}
}
}
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符**argv){
mkfifo(“/tmp/test”,0666);
而(1){
int fd,状态;
如果((fd=open(“/tmp/test”,仅限O_WRONLY))=-1){
perror(“开放式失败”);
返回1;
}
printf(“打开的管道”);
字符a='a';
int f=fork();
如果(f==-1){
佩罗尔(“福克”);
出口(1);
}else如果(f==0){
//这是通过子进程实现的
if(写入(fd,&a,1)=-1){
关闭(fd);
perror(“开放式失败”);
返回1;
}
}否则{
//这是父进程
int w=等待PID(f,&status,WUNTRACED | WCONTINUED);
如果(w==-1){
佩罗(“waitpid”);
退出(退出失败);
}
}
}
}
因为您不必检查write
的返回,所以您甚至没有注意到它失败了。(也就是说,它不是无休止地流入管道;它只是对你撒谎,并打印“向管道写入…”,而没有向管道写入。)
阻止写入的唯一方法是填充管道。但那不是你的问题。问题是管道已经终止。如果您想保持该管道打开,则需要一些进程仍处于活动状态,从中读取数据。例如,您可以在其他shell中执行sleep500
。或者只需打开fifo在程序中进行写入读取。(例如,添加行open(“/tmp/fifo”,仅限ordu);
)
更奇怪的问题是;为什么您的程序没有从SIGPIPE终止?既然您不必检查
write的返回,您甚至没有注意到它失败了。(也就是说,它不是无休止地流入管道;它只是对你撒谎,并打印“向管道写入…”,而没有向管道写入。)
阻止写入的唯一方法是填充管道。但那不是你的问题。问题是管道已经终止。如果您想保持该管道打开,则需要一些进程仍处于活动状态,从中读取数据。例如,您可以在其他shell中执行sleep500
。或者只需打开fifo在程序中进行写入读取。(例如,添加行open(“/tmp/fifo”,仅限ordu);
)
更奇怪的问题是;为什么程序没有从SIGPIPE终止?您可以尝试执行您正在尝试的操作,但是您必须了解,您必须在shell端将读取限制为一个字符,因为不会有'\n'
写入管道。此外,您可以写入
的次数比shell读取
的次数多得多。例如,您可以按照Pursell先生的建议添加验证,以确保您的C程序正常运行,并在write
上使用类似以下内容进行阻塞:
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main (int argc, char **argv) {
int fd;
errno = 0;
if (mkfifo (argc > 1 ? argv[1] : "/tmp/test", 0666)) {
perror ("mkfifo failed");
return 1;
}
if ((fd = open ("/tmp/test", O_WRONLY)) == -1) {
perror ("open failed");
return 1;
}
printf ("Opened\n");
char a = 'a';
while (1) {
printf ("Writing to pipe...\n");
if (write (fd, &a, 1) == -1) {
perror ("open failed");
return 1;
}
}
return 0;
}
您将写入
,直到fifo缓冲区已满,导致写入管道的比您读取的多。
带有叉的粗略示例
下面是一个使用fork
生成子进程的粗略示例,以确保您的C程序在编写shell时始终处于阻塞状态。本例仅限于3次重复,但您可以使用while(1)
连续循环。我还添加了一个快速计数器,用于写入(只是出于好奇)
示例Shell读取/输出
read: a
read: a
read: a
read: a
read: a
read: a
read: a
read: a
read: a
read: a
$ ./bin/pipe_write_shell_fork
Opened
0 - Writing to pipe...
1 - Writing to pipe...
2 - Writing to pipe...
3 - Writing to pipe...
4 - Writing to pipe...
...
138 - Writing to pipe...
139 - Writing to pipe...
140 - Writing to pipe...
shell read complete. restarting
Opened
0 - Writing to pipe...
1 - Writing to pipe...
2 - Writing to pipe...
3 - Writing to pipe...
4 - Writing to pipe...
...
130 - Writing to pipe...
131 - Writing to pipe...
shell read complete. restarting
Opened
0 - Writing to pipe...
1 - Writing to pipe...
2 - Writing to pipe...
3 - Writing to pipe...
4 - Writing to pipe...
...
144 - Writing to pipe...
145 - Writing to pipe...
shell read complete. done
$ declare -i c=0; while test "$c" -lt 10 && read -n 8 ch; do \
echo "read: $ch"; ((c++)); done </tmp/test
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
$declare-ic=0;测试“$c”-lt 10和读取-n 8通道;做\
echo“read:$ch”;(c++);完成您可以尝试执行您正在尝试的操作,但是您必须了解,您必须将shell端的读取限制为一个字符,因为不会有'\n'
写入管道。此外,您可以写入
的次数比shell读取
的次数多得多。例如,您可以按照Pursell先生的建议添加验证,以确保您的C程序正常运行,并在write
上使用类似以下内容进行阻塞:
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main (int argc, char **argv) {
int fd;
errno = 0;
if (mkfifo (argc > 1 ? argv[1] : "/tmp/test", 0666)) {
perror ("mkfifo failed");
return 1;
}
if ((fd = open ("/tmp/test", O_WRONLY)) == -1) {
perror ("open failed");
return 1;
}
printf ("Opened\n");
char a = 'a';
while (1) {
printf ("Writing to pipe...\n");
if (write (fd, &a, 1) == -1) {
perror ("open failed");
return 1;
}
}
return 0;
}
您将写入
,直到fifo缓冲区已满,导致写入管道的比您读取的多。
带有叉的粗略示例
下面是一个使用fork
生成子进程的粗略示例,以确保您的C程序在编写shell时始终处于阻塞状态。本例仅限于3次重复,但您可以使用while(1)
连续循环。我还添加了一个快速计数器,用于写入(只是出于好奇)
示例Shell读取/输出
read: a
read: a
read: a
read: a
read: a
read: a
read: a
read: a
read: a
read: a
$ ./bin/pipe_write_shell_fork
Opened
0 - Writing to pipe...
1 - Writing to pipe...
2 - Writing to pipe...
3 - Writing to pipe...
4 - Writing to pipe...
...
138 - Writing to pipe...
139 - Writing to pipe...
140 - Writing to pipe...
shell read complete. restarting
Opened
0 - Writing to pipe...
1 - Writing to pipe...
2 - Writing to pipe...
3 - Writing to pipe...
4 - Writing to pipe...
...
130 - Writing to pipe...
131 - Writing to pipe...
shell read complete. restarting
Opened
0 - Writing to pipe...
1 - Writing to pipe...
2 - Writing to pipe...
3 - Writing to pipe...
4 - Writing to pipe...
...
144 - Writing to pipe...
145 - Writing to pipe...
shell read complete. done
$ declare -i c=0; while test "$c" -lt 10 && read -n 8 ch; do \
echo "read: $ch"; ((c++)); done </tmp/test
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
read: aaaaaaaa
$declare-ic=0;测试“$c”-lt 10和读取-n 8通道;做\
echo“read:$ch”;((c)+