如何从管道中读取长数据?

发布于 2024-11-18 18:09:45 字数 469 浏览 3 评论 0原文

这涉及进程间通信中的未命名管道。 我有一个管道,一个进程在其中存储一个值,另一个进程想要读取这个数值(int 或 long)。

这里有很好的描述 http://tldp.org/LDP/lpg/node11.html 如何在 C 中创建管道。我的问题是如何从管道中读取 long 或 int 。

从上面提到的页面摘录:

/* Read in a string from the pipe */
int nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);

嗯,总的来说,我不知道在 C 中如何处理管道(它就像一个文件?)以及如何从中读取字符串以外的数据。

This concerns unnamed pipes in interprocess communication.
I have a pipe and one process stores a value in it and the other want to read this valus which is numerical, either int or long.

It is well described here http://tldp.org/LDP/lpg/node11.html how to create pipes in C. My question is how to read a long or int from a pipe.

extract from above mentioned page:

/* Read in a string from the pipe */
int nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);

well, in generell i have no idea how a pipe is treated in C (It is like a file?) and how i can read data other than a string from it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

叹倦 2024-11-25 18:09:45

您无法“真正”从管道中读取long。您从管道中读取一个字节序列,如果您可以定义这些字节代表的某个协议,那么您就读取了一个 long。

假设管道的两端都使用相同的 long 存储表示,如果它们是使用相同架构的相同编译器编译的,或者使用不同编译器但使用相同的编译器,则它们是这样的ABI,那么您可以在一端写入(fd, &src_long, sizeof(long));,然后读取(fd, &dst_long, sizeof(long));代码> 在另一端。加上或减去通常的混乱以确保 I/O 不会提前完成。

You can't "really" read a long from a pipe. You read a sequence of bytes from a pipe, and if you can define some protocol for which long those bytes represent, then you've read a long.

Assuming that both ends of the pipe are using the same storage representation for long, which they are if they were compiled with the same compiler for the same architecture, or for that matter with different compilers but using the same ABI, then you can write(fd, &src_long, sizeof(long)); at one end, and read(fd, &dst_long, sizeof(long)); at the other end. Plus or minus the usual messing about to ensure the I/O didn't finish early.

山人契 2024-11-25 18:09:45

管道就像文件一样,只是它是不可查找的。当您读取数据时,它会从管道中“消失”,并且无法再次读取。

您可以像从任何其他文件中一样读取数据结构。可以用scanf、fstream>>来完成或者使用 read() 和 union。

A pipe is just like a file, except it is unseekable. When you read data, it is "gone" from the pipe and can't be read again.

You would read a datastructure like you would from any other file. It can be done with scanf, fstream>> or with a read() and a union.

春夜浅 2024-11-25 18:09:45

由于管道的两端都在同一台机器上,因此您不必担心机器架构的差异;如果你改变问题来讨论套接字,你就不得不担心这个问题。

您可以使用以下方法向管道写入一个长整型值:

long l = 0x01020304L
if (write(pipe_w_fd, &l, sizeof(l)) != sizeof(l))
    ...handle error...

您可以使用以下方法从管道中读取值:

long l;
if (read(pipe_r_fd, &l, sizeof(l)) != sizeof(l))
    ...handle error...

如果您必须处理不同的机器体系结构,则可以将值格式化为与平台无关的格式(例如大端)并在一端写入该数据,在另一端读取与平台无关的数据并转换回本地机器特定的格式。

Since both ends of your pipe are on the same machine, you don't have to worry about differences in machine architectures; if you changed the question to discuss sockets, you would have to worry about that.

You can write a long to the pipe using:

long l = 0x01020304L
if (write(pipe_w_fd, &l, sizeof(l)) != sizeof(l))
    ...handle error...

And you can read the value off the pipe using:

long l;
if (read(pipe_r_fd, &l, sizeof(l)) != sizeof(l))
    ...handle error...

If you had to deal with different machine architectures, you'd format the value into a platform-neutral format (e.g. big-endian) and write that on one end, and read the platform-neutral data on the other end and convert back to the local machine-specific format.

我一直都在从未离去 2024-11-25 18:09:45

取决于如何发送。如果您有一些协议/帧约定,则必须读取帧然后提取 int。如果您只发送 int 本身,则可以读取 sizeof(int) 字节,然后直接使用缓冲区中的字节:

int foo = *((int*) readbuffer);

由于管道是本地的,因此您不必(在大多数情况下)关心字节序和大小这里。

Depends on how it's sent. If you have some protocol / framing convention, you'll have to read the frame and then extract the int. If you're sending just the int itself, you can read sizeof(int) bytes and then use the bytes in the buffer directly:

int foo = *((int*) readbuffer);

Since the pipe is local, you won't have to (in most cases) care about endianness and sizes here.

真心难拥有 2024-11-25 18:09:45

嗯,总的来说,我不知道如何在 C 中处理管道(它就像一个文件?)

是的。

以及如何从中读取字符串以外的数据。

这是简单的情况,假设 long 是二进制的并且在系统中具有相同的大小。如果 long 被写为字符串,则读取字符串然后找到 long。

long mylong;
int nbytes = read(fd[0], &mylong, sizeof(long));

well, in generell i have no idea how a pipe is treated in C (It is like a file?)

Yes.

and how i can read data other than a string from it.

This is the naive case, which assumes the long is binary and the same size in the system. If the long was written as a string, read a string then find the long.

long mylong;
int nbytes = read(fd[0], &mylong, sizeof(long));
你列表最软的妹 2024-11-25 18:09:45

它被视为一个文件。我会阅读 scanf 来看看您可以轻松解析哪些数据。像整数、十六进制或八进制整数这样的东西可以很容易地解析,甚至指针也可以解析。 Long 并不那么简单,但您可以从字符串 (%s) 中解析出 long,然后将其存储在 long 中。

http://beej.us/guide/bgc/output/html/multipage /scanf.html

It is treated like a file. I would read up on scanf to see what data you can easily parse. Things like integers, and integers in hex or oct can be easily parsed, even pointers can be parsed. Longs are not as simple, but you can just parse a long from a string (%s) and store it in a long later.

http://beej.us/guide/bgc/output/html/multipage/scanf.html

原谅过去的我 2024-11-25 18:09:45

您可以这样做:

long l;

if (read(fd[0], &l, sizeof(l)) != sizeof(l))
{
   /* TODO: handle this */
}

通过将序列化类型设置为long,您会失去一些灵活性,因为读取此数据的任何人都可能会得到不同的字节顺序或不同的大小长。举个例子,假设您 forkdup2(fd[1], 1) t
最终在子进程中执行 SSH 命令...现在数据可能来自另一台机器,并且会出现问题。为了避免这种情况,你可以这样做:

/* Type of l has a predictable size. */
uint32_t l;

if (read(fd[0], &l, sizeof(l)) != sizeof(l))
{
   /* TODO: handle this */
}

/* Convert byte order of what we just read */
l = ntohl(l);

实际上,以 32 位增量读取有点奇怪......你应该考虑的是提出一种消息格式并读取更大的消息块一次数据。实现此目的的一个好方法是为每个信息量提供一个标头,指示后续内容的大小、消息类型等。或者,如果您觉得这不吸引人,您可以考虑将序列化为文本。这也将为字节顺序问题提供一个不错的答案。

You can do this:

long l;

if (read(fd[0], &l, sizeof(l)) != sizeof(l))
{
   /* TODO: handle this */
}

By having your serialization type be long you lose some flexibility here, as it may be possible that whoever is reading this data ends up with different byte order or a different size for long. Imagine, as an example, that you fork and dup2(fd[1], 1) t
hen end up exec-ing an SSH command in the child process... Now the data potentially comes from another machine, and there will be problems. To avoid it you can do something like this:

/* Type of l has a predictable size. */
uint32_t l;

if (read(fd[0], &l, sizeof(l)) != sizeof(l))
{
   /* TODO: handle this */
}

/* Convert byte order of what we just read */
l = ntohl(l);

In actuality it's a little strange to read in 32-bit increments... What you should consider is to come up with a message format and read larger chunks of data at a time. A good way to accomplish this is for each quantity of information to have a header that indicates the size of what follows, message type, etc. Or if you don't find this appealing you can consider having your serialization be text. This would also provide a decent answer to the endianness problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文