免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 711 | 回复: 8

[内核入门] 关于fork进程中copy_files的疑问,求解答 [复制链接]

论坛徽章:
0
发表于 2016-03-21 09:21 |显示全部楼层
在fork进程时,当COPY_FILES flag没有设置时,意味着继承之后的打开的文件信息需要另立门户,但是在如下代码中,仅仅是递增了file中f_count计数,并没有深度复制file机构中的信息。举个例子,fork后地子进程执行seek操作,同样也会导致父进程seek啊,不是很明白,求解惑。

struct files_struct *oldf, *newf;
struct file **old_fds, **new_fds;

......此处省略

old_fds = oldf->fd;
new_fds = newf->fd;

......此处省略

for (i = open_files; i != 0; i--) {
    struct file *f = *old_fds++;
    if (f)
        get_file(f);
        *new_fds++ = f;

}

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
发表于 2016-03-21 16:41 |显示全部楼层
这是期望的行为吧?

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
发表于 2016-03-21 16:45 |显示全部楼层
  1. [~]$ cat file.c
  2. #include <unistd.h>
  3. #include <fcntl.h>
  4. int main()
  5. {
  6.         int fd = open("file.txt", O_WRONLY | O_TRUNC | O_CREAT);
  7.         write(fd, "1\n2\n3\n4\n", 8);
  8.         if (fork() == 0) {
  9.                 lseek(fd, 0, 0);
  10.                 write(fd, "a\n", 2);
  11.         } else {
  12.                 sleep(3);
  13.                 write(fd, "b\n", 2);
  14.         }
  15. }
  16. [~]$ cat file.txt
  17. a
  18. b
  19. 3
  20. 4
复制代码

论坛徽章:
0
发表于 2016-03-22 15:02 |显示全部楼层
看来书上写的有错啊。正确的理解应该是:
当设置CLONE_FILES,只是最顶层current->files->count ++就返回了,这就意味着子进程不仅共享父进程在fork之前已打开文件信息,还共享fork后父子进程之后打开的文件信息。
当不设置CLONE_FLAGS时,子进程仅共享fork之前父进程打开的文件。而fork之后父子进程打开的文件互不干扰。

貌似针对fork时的CLONE参数,基本可以有这样的结论:
无论CLONE参数设不设置,父子进程始终共享fork之前父进程的一些信息,而CLONE参数设置后,fork之后的行为就互不干扰了。
回复 3# nswcfd


   

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
发表于 2016-03-23 11:22 |显示全部楼层
#define CLONE_FS        0x00000200        /* set if fs info 【shared】 between processes */
#define CLONE_FILES        0x00000400        /* set if open files 【shared】 between processes */

可以看到,某些CLONE_XXX的含义,通常是【不】做deep copy,跟字面意思正好反过来了。

但也不失绝对的,比如下面的行为跟字面就是一致的。
#define CLONE_THREAD        0x00010000        /* Same thread group? */
#define CLONE_NEWNS        0x00020000        /* New namespace group? */

论坛徽章:
0
发表于 2016-03-24 15:42 |显示全部楼层
恩,谢谢解答。
我这边在学习中断的时候,看到这样的描述,对如下红色部分有疑问,能帮忙答疑一下吗?是在不理解。


1.确定与中断或异常关联的向量i (0£i£255)。

2.籍由idtr寄存器从IDT表中读取第i项(在下面的描述中,我们假定该IDT表项中包含的是一个中断门或一个陷阱门)。

3.从gdtr寄存器获得GDT的基地址,并在GDT表中查找,以读取IDT表项中的选择符所标识的段描述符。这个描述符指定中断或异常处理程序所在段的基地址。



4.确信中断是由授权的(中断)发生源发出的。首先将当前特权级CPL(存放在cs寄存器的低两位)与段描述符(存放在GDT中)的描述符特权级DPL比较,如果CPL小于DPL,就产生一个“通用保护”异常,因为中断处理程序的特权不能低于引起中断的程序的特权。对于编程异常,则做进一步的安全检查:比较CPL与处于IDT中的门描述符的DPL,如果DPL小于CPL,就产生一个“通用保护”异常。这最后一个检查可以避免用户应用程序访问特殊的陷阱门或中断门。



5.检查是否发生了特权级的变化,也就是说, CPL是否不同于所选择的段描述符的DPL。如果是,控制单元必须开始使用与新的特权级相关的栈。通过执行以下步骤来做到这点:
a.读tr寄存器,以访问运行进程的TSS段。
b.用与新特权级相关的栈段和栈指针的正确值装载ss和esp寄存器。这些值可以在TSS中找到(参见第三章的“任务状态段”一节)。
c.在新的栈中保存ss和esp以前的值,这些值定义了与旧特权级相关的栈的逻辑地址。// 到这里ss和esp寄存器已经是新特权的栈了,怎么知道以前的esp值?



    6.如果故障已发生,用引起异常的指令地址装载cs和eip寄存器,从而使得这条指令能再次被执行。

    7.在栈中保存eflag、cs及eip的内容。 // 同理这里cs还是没变化过,可以保存,但经过上述一系列步骤,eip也在随着变化啊,eip已经不是中断前的eip了啊

8.如果异常产生了一个硬错误码,则将它保存在栈中。

9.装载cs和eip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量域。这些值给出了中断或者异常处理程序的第一条指令的逻辑地址。//在这之前还一直在用户态,但栈已经切换到内核,之前保存现场的操作是在用户特权级下操作内核地址空间,这样没问题吗?


回复 4# allkillers


   

论坛徽章:
0
发表于 2016-03-24 15:43 |显示全部楼层
恩,谢谢解答。
我这边在学习中断的时候,看到这样的描述,对如下红色部分有疑问,能帮忙答疑一下吗?是在不理解。


1.确定与中断或异常关联的向量i (0£i£255)。

2.籍由idtr寄存器从IDT表中读取第i项(在下面的描述中,我们假定该IDT表项中包含的是一个中断门或一个陷阱门)。

3.从gdtr寄存器获得GDT的基地址,并在GDT表中查找,以读取IDT表项中的选择符所标识的段描述符。这个描述符指定中断或异常处理程序所在段的基地址。



4.确信中断是由授权的(中断)发生源发出的。首先将当前特权级CPL(存放在cs寄存器的低两位)与段描述符(存放在GDT中)的描述符特权级DPL比较,如果CPL小于DPL,就产生一个“通用保护”异常,因为中断处理程序的特权不能低于引起中断的程序的特权。对于编程异常,则做进一步的安全检查:比较CPL与处于IDT中的门描述符的DPL,如果DPL小于CPL,就产生一个“通用保护”异常。这最后一个检查可以避免用户应用程序访问特殊的陷阱门或中断门。



5.检查是否发生了特权级的变化,也就是说, CPL是否不同于所选择的段描述符的DPL。如果是,控制单元必须开始使用与新的特权级相关的栈。通过执行以下步骤来做到这点:
a.读tr寄存器,以访问运行进程的TSS段。
b.用与新特权级相关的栈段和栈指针的正确值装载ss和esp寄存器。这些值可以在TSS中找到(参见第三章的“任务状态段”一节)。
c.在新的栈中保存ss和esp以前的值,这些值定义了与旧特权级相关的栈的逻辑地址。// 到这里ss和esp寄存器已经是新特权的栈了,怎么知道以前的esp值?



    6.如果故障已发生,用引起异常的指令地址装载cs和eip寄存器,从而使得这条指令能再次被执行。

    7.在栈中保存eflag、cs及eip的内容。 // 同理这里cs还是没变化过,可以保存,但经过上述一系列步骤,eip也在随着变化啊,eip已经不是中断前的eip了啊

8.如果异常产生了一个硬错误码,则将它保存在栈中。

9.装载cs和eip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量域。这些值给出了中断或者异常处理程序的第一条指令的逻辑地址。//在这之前还一直在用户态,但栈已经切换到内核,之前保存现场的操作是在用户特权级下操作内核地址空间,这样没问题吗?



    回复 5# nswcfd


   

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
发表于 2016-03-25 11:01 |显示全部楼层
这是ULK里关于异常或中断的描述吧,看英文版的更清楚一些。

问题9,英文版写的很清楚,这里的cs/ip来自IDT中的Gate Descriptor(也就是第2步读的东西)

问题5c,cpu当然知道了……甚至可以假设到这一步cs/ip还没有被改变呢(直到第9步才发生变化)。

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
发表于 2016-03-25 11:02 |显示全部楼层
PS,如果对细节感兴趣的话,可以看一下邓志的《x86/x64体系探索及编程》。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

DTCC2020中国数据库技术大会

【架构革新 高效可控】2020年12月21日-23日第十一届中国数据库技术大会将在北京隆重召开。

大会设置2大主会场,20+技术专场,将邀请超百位行业专家,重点围绕数据架构、AI与大数据、传统企业数据库实践和国产开源数据库等内容展开分享和探讨,为广大数据领域从业人士提供一场年度盛会和交流平台。

http://dtcc.it168.com


大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP