是否有一个函数,int pipe(int pipefd[2])但返回FILE指针?我知道我可以FILE * fdopen(int)既文件描述符,我知道我,当我int fclose(FILE *)的FILE三分球,将关闭底层的文件描述符,所以我并不需要对其进行跟踪,但只希望是很好的与任何文件描述符完全贴或FILE指针.
int fpipe(FILE * pipes[2]) {
int result;
int pipefd[2];
FILE * pipe[2];
if (0 != (result = pipe(pipefd))) {
return result;
}
if (NULL == (pipe[0] = fdopen(pipefd[0], "r"))) {
close(pipefd[0]);
close(pipefd[1]);
return errno;
}
if (NULL == (pipe[1] = fdopen(pipefd[1], "w"))) {
fclose(pipe[0]);
close(pipefd[1]);
return errno;
}
pipes[1] = pipe[1];
pipes[0] = pipe[0];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
你的fpipe()功能接近你所需要的,并且没有标准功能来完成同样的工作,所以你需要写一些东西.没有这种标准功能的主要原因是,大多数情况下你最终会分叉,然后使用dup()或dup2()最后使用一个exec*()函数,所以在大多数情况下拥有文件流确实没什么好处.
如评论中所述,您需要决定在成功和出错时返回什么,并相应地进行管理errno.有两种合理的设计(两者都有先例):
0成功,并-1与在更详细的错误信息,失败errno变量(经典函数调用技术:看见open(),close(),read(),write(),...).0成功返回,失败时返回错误号(无需修改errno) - 这是POSIX threads(pthreads)函数使用的技术.两种设计都会pipes[]在错误时使阵列处于不确定状态.这不是不合理的; 参数数组不应该在调用之前指向有价值的文件流,fpipe()因为如果调用成功,则值将丢失.
请记住,没有标准C或POSIX库函数设置errno为零.(见POSIX errno).
以下是两种设计,通过-DUSE_PTHREAD_COMPATIBLE_DESIGN编译器命令行的存在与否来选择:
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
extern int fpipe(FILE *pipes[2]); // Should be in a header
#ifndef USE_PTHREAD_COMPATIBLE_DESIGN
// Design 1 - return -1 on failure and set errno
int fpipe(FILE *pipes[2])
{
int pipefd[2];
if (pipe(pipefd) != 0)
return -1;
if ((pipes[0] = fdopen(pipefd[0], "r")) == NULL)
{
close(pipefd[0]);
close(pipefd[1]);
return -1;
}
if ((pipes[1] = fdopen(pipefd[1], "w")) == NULL)
{
fclose(pipes[0]);
close(pipefd[1]);
return -1;
}
return 0;
}
#else
// Design 2 - return error number on failure and don't modify errno
int fpipe(FILE *pipes[2])
{
int saved_errno = errno;
int rc = 0;
int pipefd[2];
if (pipe(pipefd)) != 0)
rc = errno;
else if ((pipes[0] = fdopen(pipefd[0], "r")) == NULL)
{
rc = errno;
close(pipefd[0]);
close(pipefd[1]);
}
else if ((pipes[1] = fdopen(pipefd[1], "w")) == NULL)
{
rc = errno;
fclose(pipes[0]);
close(pipefd[1]);
}
errno = saved_errno;
return rc;
}
#endif /* USE_PTHREAD_COMPATIBLE_DESIGN */
Run Code Online (Sandbox Code Playgroud)
在函数的第一个变体中,因为if块的主体总是以结尾return,所以不需要else if用于下一个块.对于第二个变体,if块不返回,因此这else if很重要.C测试作业结果的能力在这里是一个巨大的帮助.
如果您愿意,可以if (rc != 0) pipes[0] = pipes[1] = NULL;在第二个版本的返回之前添加.您必须将这些分配放在另一个设计中的更多位置.实际上,我可能会将值设置为NULLon,然后只有pipes[0]在初始化时才重置为NULL,pipes[1]而不是.