父子之间的图像数据缓冲读/写操作尚未完成

时间:2019-03-07 15:37:29

标签: c++ ipc fread

简介和一般目标

这个问题源自this one,我试图将图像数据从孩子发送到父母。在这种情况下,问题在于使用了缓冲和非缓冲读取功能。您可以在此问题的底部找到旧问题的工作代码。

现在,我尝试将图像从父进程发送到子进程(通过从父进程调用popen生成),以显示iamge。

该图像是灰度png图像。它使用OpenCV库打开,并使用同一库的imencode函数进行编码。因此,将所得的编码数据存储到类型为std::vector的{​​{1}}结构中,即以下代码中的uchar向量。

发送一些数据没有错误

为简单起见,图像的大小被硬编码在变量img中的child中。这用于分配存储接收数据的内存。分配如下:

img_size

发送图像数据

父级使用 u_char *buf = (u_char*)malloc(img_size*sizeof(u_char)); 将编码数据(即向量img中包含的数据)写入FILE*返回的popen流中,而子级则读取数据fwrite使用fread文件描述符的转换结果作为FILE*

STDIN_FILENO

数据写入是在while循环内的块FILE * fp = fdopen(STDIN_FILENO, "r"); 个字节中执行的,而数据读取是在两次调用4096中进行读取的(我知道这很丑陋,但是会有所改变)。

编写循环如下:

fread

while (written<img.size()) { //bytes to send: 4096 or the remaining ones if less than 4096 toWrite = BUFLEN < (img.size()-written) ? BUFLEN : (img.size()-written); //total bytes that have been sent until now written += toWrite*fwrite ( img.data()+written, toWrite, 1, f ); printf("written: %ld\n", written); } 将指针返回向量结构内部使用的数组中第一个元素。 img.data()存储到现在为止已写入的字节数,它用作索引。 written返回实际已写入的块数(每个块大小为fwrite个字节),该块数用于更新toWrite

数据读取非常相似,它由以下行执行(written初始化为bytes2Copy):

4096

//read all possible bytes in blocks of 4096 until less than 4096 bytes remain elRead = fread ( buf, bytes2Copy, img_size/bytes2Copy, fp); total_bytes_read += elRead*bytes2Copy; bytes2Copy = img_size-total_bytes_read; //now less than 4096 bytes remain printf("child received %ld\n", total_bytes_read); //read remaining bytes elRead = fread ( buf+total_bytes_read, bytes2Copy, 1, fp); 是存储接收到的数据的数组。 bufbytes2Copy(即BUFLEN),还是最后一个数据块的剩余数据(例如,如果总字节为4096,则在{{1} 1}}个字节,应该是5000的另一个块。)

代码

请考虑以下示例。以下是使用4096

启动子进程的过程
5000-4096

和上面打开的过程对应于以下内容:

popen

错误

父级读取图像,对其进行编码,然后发送编码后的图像数据。

孩子以#include <stdlib.h> #include <unistd.h>//read #include "opencv2/opencv.hpp" #include <iostream> #include <sys/wait.h> #include "opencv2/opencv.hpp" #define BUFLEN 4096 using namespace cv; int main(int argc, char *argv[]) { int status; Mat frame; std::vector<uchar> img; //read image as grayscale frame = imread("/home/path/img/test.png",0); //encode image and put data into the vector buf imencode(".png",frame, img); //send the total size of vector to parent size_t toWrite = 0; size_t written= 0; FILE * f = popen("/home/path/childProcess", "w"); printf("forked\n"); while (written<img.size()) { //send the current block of data toWrite = BUFLEN < (img.size()-written) ? BUFLEN : (img.size()-written); //written += write(STDOUT_FILENO, buf.data()+written, toWrite); written += toWrite*fwrite ( img.data()+written, toWrite, 1, f ); printf("written: %ld\n", written); } wait(&status); return 0; } 为单位读取数据。但是,在第二次调用#include <stdlib.h> #include <unistd.h> #include "opencv2/opencv.hpp" #include <iostream> #include <time.h> #define BUFLEN 4096 int main(int argc, char *argv[]) { cv::Mat frame; size_t img_size = 115715; u_char *buf = (u_char*)malloc(img_size*sizeof(u_char)); size_t total_bytes_read = 0; size_t elRead =0; size_t bytes2Copy = BUFLEN; FILE * fp = fdopen(STDIN_FILENO, "r"); elRead = fread ( buf, bytes2Copy, img_size/bytes2Copy, fp); total_bytes_read += elRead*bytes2Copy; bytes2Copy = img_size-total_bytes_read; printf("child received %ld\n", total_bytes_read); elRead = fread ( buf+total_bytes_read, bytes2Copy, 1, fp); //sostituire 1 total_bytes_read += elRead*bytes2Copy;//bytes_read_tihs_loop; printf("child received %ld\n", total_bytes_read); cv::namedWindow( "win", cv::WINDOW_AUTOSIZE ); frame = cv::imdecode(cv::Mat(1,total_bytes_read,0, buf), 0); cv::imshow("win", frame); cv::waitKey(0); return 0; } 时,其中缺少少于4096个字节,它将尝试仅读取丢失的字节:在我的情况下,第二次对fread()的调用应读为{{1} }个字节(4096)。在第二个调用中,尽管父级发送了(或至少似乎发送了)所有数据,但它什么也没读。

frad为什么不读取所有丢失的字节?

我正在处理这张图片:enter image description here

在我尝试对图像进行解码时可能也会出错,因此也将不胜感激。


旧问题的工作代码

请注意,在回答了原始问题之后,我设法正确地将数据从孩子发送到了父母(另一个方向)。 有效的代码如下:

父母:

1027

孩子:

115715%4096

0 个答案:

没有答案