C Q:从管道到屏幕的读数
我正试图编写一个程序,从文件中读取一些文本并将其打印到屏幕上。父级将读取文件内容并将其写入n个管道,子级将读取并打印 到目前为止,我得到的是:C Q:从管道到屏幕的读数,c,file,pipe,C,File,Pipe,我正试图编写一个程序,从文件中读取一些文本并将其打印到屏幕上。父级将读取文件内容并将其写入n个管道,子级将读取并打印 到目前为止,我得到的是: #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <string.h> int main (void) { pid_t pid; char c; FI
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
int main (void)
{
pid_t pid;
char c;
FILE *fd;
char buf[100];
int N_CHILDREN = 2;
int p[N_CHILDREN][2];
int i,j;
for(i=0; i<N_CHILDREN; i++)
{
pipe(p[i]);
}
fd=fopen("123.txt","r");
for(j=0; j < N_CHILDREN;j++)
{
pid = fork ();
if (pid == 0)
{
close (p[j][1]);
while(read(p[j][0], &fd,sizeof(buf)) > 0)
printf("\n%c",&fd);
}
if (pid < 0)
{
//Fork Failed
fprintf (stderr, "Fork failure.\n");
return EXIT_FAILURE;
}
if ( pid > 0) //Parent
{
close (p[j][0]);
write(p[j][1], fd ,sizeof(buf));
}
}
}
#包括
#包括
#包括
#包括
#包括
内部主(空)
{
pid_t pid;
字符c;
文件*fd;
char-buf[100];
int N_CHILDREN=2;
int p[N_CHILDREN][2];
int i,j;
对于(i=0;i=0)
printf(“\n%c”,&fd);
}
if(pid<0)
{
//Fork失败了
fprintf(stderr,“Fork failure.\n”);
返回退出失败;
}
如果(pid>0)//父级
{
收盘(p[j][0]);
写入(p[j][1],fd,sizeof(buf));
}
}
}
问题是它并没有真正从文件中读取内容。我试着给它发送一个字符串,而不是从一个文件中读取,结果一切正常,两个孩子只打印了一次消息,程序就结束了
有什么想法吗?阅读这些手册后,我仍然看不出问题出在哪里。据我所知,您没有读入buf。据我所知,您没有读入buf。您混淆了C标准I/O流(使用
fopen()
;使用fprintf()编写)
等,使用fscanf()
等)读取Unix文件描述符I/O(使用open()
或pipe()
等创建,使用write()
等写入,使用read()
等读取。)
标准I/O函数将不透明的文件*
作为句柄;Unix I/O函数将文件描述符(小int)作为句柄
一旦你理解了概念上的差异,我相信你会意识到这一点
FILE *fd = ...
read(..., &fd, ...);
正在读取指向文件的指针-)您将C标准I/O流(使用
fopen()
创建;使用fprintf()
等写入;使用fscanf()
等读取)与Unix文件描述符I/O(使用open()
或pipe()创建)相混淆
等,使用write()写入(
等,使用read()读取(
等)
标准I/O函数将不透明的文件*
作为句柄;Unix I/O函数将文件描述符(小int)作为句柄
一旦你理解了概念上的差异,我相信你会意识到这一点
FILE *fd = ...
read(..., &fd, ...);
正在读取指向文件的指针--不是非常有用:-)这里有几个问题:
&fd
,这是一个文件*
,您错误地使用了read
函数。这个函数需要一个指向“缓冲区”的指针来打印,我猜这里是buf
fopen
失败read
(在子项中)的返回值,因为它是您获得的有效数据量。因此,这是之后必须打印的数据量(到标准输出)// put here all the needed includes (see manpages of functions)
// it is better to create a function for the child: the code
// is easier to read
// the child just get the file descriptor to read (the pipe)
void child(int fd) {
char buf[100]; // buffer to store data read
int ret; // the number of bytes that are read
// we read from 'fd', into 'buf'. It returns the number of bytes
// really read (could be smaller than size). Return <=0 when over
while((ret = read(fd, buf, sizeof(buf))) > 0) {
// write the 'ret' bytes to STDOUT (which as file descriptor 1)
write(1, buf, ret);
}
}
int main (void) {
pid_t pid;
char buf[100];
int N_CHILDREN = 2;
int p[N_CHILDREN][2];
int i,j, ret;
int fdi;
// create the pipes
for(i=0; i<N_CHILDREN; i++) {
if (pipe(p[i]) == -1) {
perror("pipe"); // ALWAYS check for errors
exit(1);
}
}
// open the file (with 'open' not 'fopen', more suitable for
// reading raw data
fdi = open("123.txt",O_RDONLY);
if (fdi < 0) {
perror("open"); // ALWAYS check for errors
exit(1);
}
// just spawn the children
for(j=0; j < N_CHILDREN;j++) {
pid = fork();
if (pid < 0) {
perror("fork"); // ALWAYS check for errors
exit(1);
}
if (pid == 0) { // child
close(p[j][1]); // close the writing part
child(p[j][0]); // call child function with corresp. FD
exit(0); // leave : the child should do nothing else
}
}
// don't need that part
for(j=0; j<N_CHILDREN; j++) {
close(p[j][0]); // close the read-part of pipes
}
// need to read file content, see comment in child() function
while ((ret = read(fdi, buf, sizeof(buf))) > 0) {
// write the data to all children
for(j=0; j<N_CHILDREN; j++) {
write(p[j][1], buf , ret); // we write the size we get
}
}
// close everithing
for(j=0; j<N_CHILDREN; j++) {
close(p[j][1]); // needed, see text after
}
close(fdi); // close read file
return(0); // main returns a int, 0 is "ok"
}
//将所有需要的内容放在这里(参见函数手册)
//最好为孩子创建一个函数:代码
//更容易阅读
//子级只获取要读取的文件描述符(管道)
无效子项(int-fd){
char buf[100];//用于存储读取数据的缓冲区
int ret;//读取的字节数
//我们从'fd'读入'buf'。它返回字节数
//真正读取(可能小于大小)。返回0){
//将'ret'字节写入STDOUT(作为文件描述符1)
写入(1,buf,ret);
}
}
内部主(空){
pid_t pid;
char-buf[100];
int N_CHILDREN=2;
int p[N_CHILDREN][2];
int i,j,ret;
国际直接投资;
//创建管道
对于(i=0;i这里的几个问题:
您通过传递&fd
(这是一个文件*
)错误地使用了读取
函数。这个函数需要一个指向“缓冲区”的指针来打印,我猜这里是buf
您不检查错误。例如,如果fopen
失败
您从未从文件中读取数据,因此“没有”可发送给孩子
您必须获得read
(在子项中)的返回值,因为它是您获得的有效数据量。因此,它是在此之后您必须打印的数据量(到标准输出)
下面是一个示例代码,请参见下面的注释:
// put here all the needed includes (see manpages of functions)
// it is better to create a function for the child: the code
// is easier to read
// the child just get the file descriptor to read (the pipe)
void child(int fd) {
char buf[100]; // buffer to store data read
int ret; // the number of bytes that are read
// we read from 'fd', into 'buf'. It returns the number of bytes
// really read (could be smaller than size). Return <=0 when over
while((ret = read(fd, buf, sizeof(buf))) > 0) {
// write the 'ret' bytes to STDOUT (which as file descriptor 1)
write(1, buf, ret);
}
}
int main (void) {
pid_t pid;
char buf[100];
int N_CHILDREN = 2;
int p[N_CHILDREN][2];
int i,j, ret;
int fdi;
// create the pipes
for(i=0; i<N_CHILDREN; i++) {
if (pipe(p[i]) == -1) {
perror("pipe"); // ALWAYS check for errors
exit(1);
}
}
// open the file (with 'open' not 'fopen', more suitable for
// reading raw data
fdi = open("123.txt",O_RDONLY);
if (fdi < 0) {
perror("open"); // ALWAYS check for errors
exit(1);
}
// just spawn the children
for(j=0; j < N_CHILDREN;j++) {
pid = fork();
if (pid < 0) {
perror("fork"); // ALWAYS check for errors
exit(1);
}
if (pid == 0) { // child
close(p[j][1]); // close the writing part
child(p[j][0]); // call child function with corresp. FD
exit(0); // leave : the child should do nothing else
}
}
// don't need that part
for(j=0; j<N_CHILDREN; j++) {
close(p[j][0]); // close the read-part of pipes
}
// need to read file content, see comment in child() function
while ((ret = read(fdi, buf, sizeof(buf))) > 0) {
// write the data to all children
for(j=0; j<N_CHILDREN; j++) {
write(p[j][1], buf , ret); // we write the size we get
}
}
// close everithing
for(j=0; j<N_CHILDREN; j++) {
close(p[j][1]); // needed, see text after
}
close(fdi); // close read file
return(0); // main returns a int, 0 is "ok"
}
//将所有需要的内容放在这里(参见函数手册)
//最好为孩子创建一个函数:代码
//更容易阅读
//子级只获取要读取的文件描述符(管道)
无效子项(int-fd){
char buf[100];//用于存储读取数据的缓冲区
int ret;//读取的字节数
//我们从'fd'读入'buf'。它返回字节数
//真正读取(可能小于大小)。返回0){
//将'ret'字节写入STDOUT(作为文件描述符1)
写入(1,buf,ret);
}
}
内部主(空){
pid_t pid;
char-buf[100];
int N_CHILDREN=2;
int p[N_CHILDREN][2];
int i,j,ret;
国际直接投资;
//创建管道
对于(i=0;iread(p[j][0],&fd,sizeof(buf))
?fd
是一个文件*
,您可能指的是buf
?之后,您不能将“缓冲区”打印为“%c”。注意:编译时总是带有所有警告,您会看到几个问题(不是全部,而是几个)。至少您会看到,read
是用&fd
调用的,这是错误的。read(p[j][0],&fd,sizeof(buf))
?fd
是一个文件*
,您可能是指buf
?之后,您不能将“缓冲区”打印为“%c”。注意:始终使用所有警告进行编译,您会看到一些问题(不是全部,但有几个)。至少你会看到阅读