问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

dup2的书目摘抄

发布网友 发布时间:2022-04-12 19:20

我来回答

2个回答

懂视网 时间:2022-04-12 23:41


update 2014.04.10

今天有了“更深”的认识吧

int dup2(int filedes1,int filedes2);
是把filedes2指向的流关闭,而重定向到filedes1指向的流,此时filedes1和filedes2均指向同一个流。

就这么简单。。。。

热心网友 时间:2022-04-12 20:49

下面内容选自《UNⅨ环境高级编程》
Stevens said:
⑴ 每个进程在进程表中都有一个记录项,每个记录项中有一张打开文件描述符表,可将视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是:
(a) 文件描述符标志。
(b) 指向一个文件表项的指针。
⑵ 内核为所有打开文件维持一张文件表。每个文件表项包含:
(a) 文件状态标志(读、写、增写、同步、非阻塞等)。
(b) 当前文件位移量。
(c) 指向该文件v节点表项的指针。
图示:
文件描述符表
------------
fd0 0 | p0 -------------> 文件表0 ---------> vnode0
------------
fd1 1 | p1 -------------> 文件表1 ---------> vnode1
------------
fd2 2 | p2
------------
fd3 3 | p3
------------
... ...
... ...
------------ 假设进程A拥有一个已打开的文件描述符fd3,它的状态如下:
进程A的文件描述符表(before p2)
------------
fd0 0 | p0
------------
fd1 1 | p1 -------------> 文件表1 ---------> vnode1
------------
fd2 2 | p2
------------
fd3 3 | p3 -------------> 文件表2 ---------> vnode2
------------
... ...
... ...
------------
经下面调用:
n_fd = p2(fd3,STDOUT_FILENO);后进程状态如下:
进程A的文件描述符表(after p2)
------------
fd0 0 | p0
------------
n_fd 1 | p1 ------------
------------ \
fd2 2 | p2 \
------------ _\|
fd3 3 | p3 -------------> 文件表2 ---------> vnode2
------------
... ...
... ...
------------
解释如下:
n_fd = p2(fd3,STDOUT_FILENO)表示n_fd与fd3共享一个文件表项(它们的文件表指针指向同一个文件表项),n_fd在文件描述符表中的位置为 STDOUT_FILENO的位置,而原先的STDOUT_FILENO所指向的文件表项被关闭,我觉得上图应该很清晰的反映出这点。按照上面的解释我们就可以解释CU中提出的一些问题:
⑴ p2的第一个参数是不是必须为已打开的合法filedes? -- 答案:必须。
⑵ p2的第二个参数可以是任意合法范围的filedes值么? -- 答案:可以,在Unix其取值区间为[0,255]。
另外感觉理解p2的一个好方法就是把fd看成一个结构体类型,就如上面图形中画的那样,我们不妨把之定义为:
struct fd_t {
int index;
filelistitem *ptr;
};
然后p2匹配index,修改ptr,完成p2操作。
在学习p2时总是碰到“重定向”一词,上图完成的就是一个“从标准输出到文件的重定向”,经过p2后进程A的任何目标为STDOUT_FILENO的I/O操作如printf等,其数据都将流入fd3所对应的文件中。下面是一个例子程序:
#define TESTSTR Hello p2\n
int main() {
int fd3;
fd3 = open(testp2.dat,0666);
if (fd3 < 0) {
printf(open error\n);
exit(-1);
}
if (p2(fd3,STDOUT_FILENO) < 0) {
printf(err in p2\n);
}
printf(TESTSTR);
return 0;
}
其结果就是你在testp2.dat中看到Hello p2。 CU上有这样一个帖子,就是如何在重定向后再恢复原来的状态?首先大家都能想到要保存重定向前的文件描述符。那么如何来保存呢,象下面这样行么?
int s_fd = STDOUT_FILENO;
int n_fd = p2(fd3,STDOUT_FILENO);
还是这样可以呢?
int s_fd = p(STDOUT_FILENO);
int n_fd = p2(fd3,STDOUT_FILENO);
这两种方法的区别到底在哪呢?答案是第二种方案才是正确的,分析如下:按照第一种方法,我们仅仅在表面上保存了相当于fd_t(按照我前面说的理解方法)中的index,而在调用p2之后,ptr所指向的文件表项由于计数值已为零而被关闭了,我们如果再调用p2(s_fd,fd3)就会出错(出错原因上面有解释)。而第二种方法我们首先做一下复制,复制后的状态如下图所示:
进程A的文件描述符表(after p)
------------
fd0 0 | p0
------------
fd1 1 | p1 -------------> 文件表1 ---------> vnode1
------------ /|
fd2 2 | p2 /
------------ /
fd3 3 | p3 -------------> 文件表2 ---------> vnode2
------------ /
s_fd 4 | p4 ------/
------------
... ...
... ...
------------
调用p2后状态为:
进程A的文件描述符表(after p2)
------------
fd0 0 | p0
------------
n_fd 1 | p1 ------------
------------ \
fd2 2 | p2 \
------------ _\|
fd3 3 | p3 -------------> 文件表2 ---------> vnode2
------------
s_fd 4 | p4 ------------->;文件表1 ---------> vnode1
------------
... ...
... ...
------------
p(fd)的语意是返回的新的文件描述符与fd共享一个文件表项。就如after p图中的s_fd和fd1共享文件表1一样。
确定第二个方案后重定向后的恢复就很容易了,只需调用p2(s_fd,n_fd);即可。下面是一个完整的例子程序:
#define TESTSTR Hello p2\n
#define SIZEOFTESTSTR 11
int main() {
int fd3;
int s_fd;
int n_fd;
fd3 = open(testp2.dat,0666);
if (fd3 < 0) {
printf(open error\n);
exit(-1);
}
/* 复制标准输出描述符 */
s_fd = p(STDOUT_FILENO);
if (s_fd < 0) {
printf(err in p\n);
}
/* 重定向标准输出到文件 */
n_fd = p2(fd3,STDOUT_FILENO);
if (n_fd < 0) {
printf(err in p2\n);
}
write(STDOUT_FILENO,TESTSTR,SIZEOFTESTSTR); /* 写入testp2.dat中 */
/* 重定向恢复标准输出 */
if (p2(s_fd,n_fd) < 0) {
printf(err in p2\n);
}
write(STDOUT_FILENO,TESTSTR,SIZEOFTESTSTR); /* 输出到屏幕上 */
return 0;
}
注意这里我在输出数据的时候我是用了不带缓冲的write库函数,如果使用带缓冲区的printf,则最终结果为屏幕上输出两行Hello p2,而文件testp2.dat中为空,原因就是缓冲区作怪,由于最终的目标是屏幕,所以程序最后将缓冲区的内容都输出到屏幕。 由fork调用得到的子进程和父进程的相同文件描述符共享同一文件表项,如下图所示:
父进程A的文件描述符表
------------
fd0 0 | p0
------------
fd1 1 | p1 -------------> 文件表1 ---------> vnode1
------------ /|\
fd2 2 | p2 |
------------ |
|
子进程B的文件描述符表 |
------------ |
fd0 0 | p0 |
------------ |
fd1 1 | p1 ---------------------|
------------
fd2 2 | p2
------------
所以恰当的利用p2和p可以在父子进程之间建立一条“沟通的桥梁”。这里不详述。 灵活的利用p/p2可以给你带来很多强大的功能,花了一些时间总结出上面那么多,不知道自己理解的是否透彻,只能在以后的实践中慢慢探索了。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
求助:补全成语. _然而止、_然不屈、_然四顾、_然若失、_然而至、_然拒绝、_然无声... 我姑妈(姑妈去世),现奶奶的房产 姑妈的女儿有继承权吗? 丈夫去世遗产应该能怎么分配 《人世间》骆士宾遗产股权归谁所有 为什么说曹珊不应该得罪水自流_百 ... 有谁知我国十大元帅及十大上将? 解放中国的10大元帅是那几个? 对中国有何影响? 中国历史上的十大元帅 为什么中国过去有元帅现在没有了 ...想看中国80年代、90年代热播的电视剧,《渴望》、《蛙女》等,越多... 孩子身上老起红疙瘩,*的难受,抹过好多药膏都不管用,怎么办??? 宝宝过敏身上起红疙瘩怎么办 华为p40pro值得买不? 我的华为p40pro手机用户改进体验计划更新于七月份而我买的时候是十月份是否是翻新机_百度问一问 我想开个包店麻烦各位有才人士给取个名字 给手工花瓶取一个古风的名字 你好,我想请问下,我90年腊月二十五下午2点42出生 叫李邱亚 貌似缺火?想改个名字,能麻烦帮我看下吗? 请帮我取个店名? 古代的笔筒叫什么? 想给我的作品起个名字 笔筒笔架镇木可以取名什么 取几个名字,这是一个笔筒 雕有孔雀的小叶紫檀笔筒能取个什么优雅的名字呢? 学校要交工艺品 别人用纸折成小的形状然后插成了个笔筒~求一个好听的名字 拜托~_百度问一问 与笔筒有关的名字大全 用易拉罐做一个笔筒取一个名字怎么才好听? 股票A股B股划转 股票哪些A股既属于上海本地板块,又有B股? 今年还有b股转a股股票吗 用dup2修改了stdin_fileno的文件描述符的问题 75位艺人注销200家公司,为什么大家集中注销公司? 为什么要先注销企业再分配 公司注销为什么都选择快注销呢? 适合玩VR的笔记本有哪些 笔记本能玩vr游戏吗 笔记本电脑如何玩VR游戏,需要什么样的配置 用哪个牌子笔记本电脑制作VR游戏好?系统配制需要什么功能? 配arpara 的PCVR游戏套装的话电脑要什么配置? 兄弟们vr玩游戏没那种的爽?pc的还是那种一体机?电脑配置要求是什么? 请推荐一些电脑,电脑品牌(要能连vr玩游戏那种配置) 笔记本1060玩vr会不会比较吃力 dup2 文件重定位 哪位高手帮我看看下面这个程序为什么会出现那个警告?? 大名府39度有20年的吗 大名府滴溜酒春夏秋冬多少钱 嘴周围变黑是什么原因? 嘴巴外边一圈发黑是什么原因? 嘴唇周围有黑圈是怎么回事 linux dup2()函数怎么不能重定向标准输出(STDOUT)到文件? 嘴唇周围为什么会又一圈黑? 嘴唇周围会看起来很黑为什么?