返回介绍

fileno() 返回描述符号

发布于 2024-10-10 23:21:38 字数 3346 浏览 0 评论 0 收藏 0

每打开一个文件,操作系统都会在描述符表中新注册一项。假设你打开了某个文件:

FILE *my_file = fopen("guitar.mp3", "r");

操作系统会打开 guitar.mp3 文件,然后返回一个指向它的指针,操作系统还会遍历描述符表寻找空项,把新文件注册在其中。

那么如何根据文件指针知道它是几号描述符呢?答案是调用 fileno() 函数。

在失败时不返回-1 的函数很少,fileno() 就是其中之一。只要你把打开文件的指针传给 fileno() ,它就一定会返回描述符编号。

dup2() 复制数据流

每次打开文件都会使用描述符表中新的一项。但如果你想修改某个已经注册过的数据流,比如想让 3 号描述符重新指向其他数据流,该怎么做?可以用 dup2() 函数,dup2() 可以复制数据流。假设你在 4 号描述符中注册了 guitar.mp3 文件指针,下面这行代码就能同时把它连接到 3 号描述符:

虽然 guitar.mp3 文件只有一个,与它相连的数据流也只有一条,但数据流(即 FILE* )同时注册在了文件描述符 3 和 4 中。

既然你已经学会了如何在描述符表中查找文件和修改数据流,也就能把进程的标准输出重定向到某个文件。

还在为错误代码烦恼?

每次你在系统调用时都需要反反复复写那些错误处理代码。还犹豫什么!赶快使用我们的独家秘方,我们将向你展示如何重用错误代码,从此你将告别重复代码:

下面两段代码一看头就大:

有没有办法可以消除重复代码呢?当然有!只要创建一个 error() 函数,就可以一劳永逸。

error() 函数是什么?这些 return 怎么处理?总不见得也移到 error() 函数里吧?

不需要!exit() 系统调用是结束程序的最快方式。完全不用操心怎么返回主函数,直接调用 exit(),你的程序就会灰飞烟灭!

首先,需要把处理代码放到一个单独的 error() 函数中,然后把 return 语句换成 exit() 系统调用。

现在就可以把那些烦人的错误检查代码换成:pid_t pid = fork();if (pid == -1) { error("无法克隆进程");}if (execle(...) == -1) { error("无法运行脚本");}







这么做简单多了!

警告:每次程序执行只有一次调用 exit() 的机会,“程序突然结束恐惧症”患者慎用。

磨笔上阵

程序把 rssgossip.py 脚本的输出保存到 stories.txt 文件中。程序只搜索一个 RSS 源,其他都和 newshound 一样。程序少了一行把子进程的标准输出重定向到 stories.txt 的代码,你能补出来吗?你可能用到描述符表的知识。

 

磨笔上阵解答

程序把 rssgossip.py 脚本的输出保存到 stories.txt 文件中。程序只搜索一个 RSS 源,其他都和 newshound 一样。程序少了一行把子进程的标准输出重定向到 stories.txt 的代码,凭借对描述符表的了解,你把它补了出来。你写对了吗?程序把子进程(脚本程序)的描述符表改成了这样:也就是说当 rssgossip.py 把数据发往标准输出时,数据应该出现在 stories.txt 文件中。

#数据流 0 键盘 1stories.txt 文件 2 屏幕 3stories.txt 文件

试驾

编译运行程序,将看到:

发生了什么事?

当程序用 fopen() 打开 stories.txt 文件时,操作系统把文件 f 注册到了描述符表中,fileno(f) 是文件 f 使用的描述符编号,而 dup2() 函数设置了标准输出描述符(1 号),让它也指向了该文件。

脑力风暴

假设 RSS 源中的确有你要找的新闻,可为什么程序结束以后 stories.txt 还是空的?

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文