22.2 父子进程操作文件

文件操作由两种模式:

  IO 系统调用操作文件

  标准C IO 操作文件

看代码:

  1. #include <unistd.h>
  2. #include <string.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6.  
  7. int g_val = ;//全局变量,存放在数据段
  8.  
  9. int main(void)
  10. {
  11. int a_val = ;//局部变量,调用的时候存放在栈中
  12. static int s_val = ;//静态变量,存放在数据段
  13. printf("pid: %d", getpid());
  14.  
  15. FILE *fp = fopen("s.txt", "w");
  16. int fd = open("s_fd.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG);
  17.  
  18. char *s = "hello world";
  19. ssize_t size = strlen(s) * sizeof(char);
  20.  
  21. /* fork 之前,为父进程调用 */
  22. fprintf(fp, "s: %s, pid: %d\n", s, getpid());//标准 IO 写入(带缓存),针对文件操作的是全缓存
  23. write(fd, s, size); //内核提供的 IO 系统调用(不带缓存)
  24.  
  25. pid_t pid;
  26. pid = fork();//创建子进程
  27. //在 fork 后,会运行两个进程(父进程和子进程)
  28. if(pid < ) {
  29. perror("fork error");
  30. } else if(pid > ) {
  31. //父进程(在父进程中返回的是子进程的 pid)
  32. //父进程执行的代码
  33. g_val = ;
  34. a_val = ;
  35. s_val = ;
  36.  
  37. printf("I am parent process pid is %d, ppid is %d, fork return is %d\n",
  38. getpid(), getppid(), pid);
  39. printf("g_val: %p, a_val: %p, s_val: %p\n", &g_val, &a_val, &s_val);
  40. } else {
  41. //子进程(在子进程中 fork 返回的是0)
  42. //子进程执行的代码
  43. g_val = ;
  44. a_val = ;
  45. s_val = ;
  46. printf("I am child process pid is %d, ppid is %d, fork return is %d\n",
  47. getpid(), getppid(), pid);
  48. printf("g_val: %p, a_val: %p, s_val: %p\n", &g_val, &a_val, &s_val);
  49. }
  50.  
  51. //这里的代码是父子进程都要执行的代码,写入父子进程各自的缓存当中
  52. fprintf(fp, " pid: %d, g_val: %d, a_val: %d, s_val: %d\n", getpid(), g_val, a_val, s_val);
  53. sleep();
  54.  
  55. return ;
  56. }

  编译运行后,两个文件都生成了。

  

  父进程文件 s.txt

  

  子进程文件 s_fd.txt

  

  系统调用不经过缓存,执行 write 后就直接写进了文件当中,标准IO是写入缓存了。

  创建的缓存是在堆当中的,我们的代码是在 fork 之前,那么缓存就在父进程的虚拟空间的堆当中,当 fork 之后,子进程会 COPY 一份父进程的堆空间。

  同样 fork 之后也由一份写入缓存的 fprintf,此时是各自写入各自的缓存,在结束的时候父子进程都会清缓存,都会写入 fp 当中

  

22.3 操作文件时的内核结构体变化

  • 子进程只继承父进程的文件描述符表,不继承但共享文件表项和 i-node
  • 父进程创建一个子进程后,文件表项中的引用计数器加1 变成 2,当父进程作 close 操作后,计数器减 1,子进程还是可以使用文件表项(即子进程还是可以操作文件),只有当计数器为 0 时,才会释放文件表项。

  

  运行 fork:

  

  例子:父进程调节文件偏移量,子进程写入

  process_append.c

  1. #include <unistd.h>
  2. #include <fcntl.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6.  
  7. int main(int argc, char *argv[])
  8. {
  9. if(argc < )
  10. {
  11. fprintf(stderr, "usage: %s file\n", argv[]);
  12. exit();
  13. }
  14.  
  15. int fd = open(argv[], O_WRONLY);
  16. if(fd < )
  17. {
  18. perror("open error");
  19. exit();
  20. }
  21.  
  22. pid_t pid = fork();
  23. if(pid < )
  24. {
  25. perror("fork error");
  26. exit();
  27. }
  28. else if(pid > )
  29. {//父进程将文件偏移量调整到文件尾部
  30. if(lseek(fd, 0L, SEEK_END) < ) {
  31. perror("lseek error");
  32. exit();
  33. }
  34. }
  35. else
  36. {//子进程从文件尾部追加内容
  37. char *str = "hello child";
  38. ssize_t size = strlen(str) * sizeof(char);
  39.  
  40. sleep();//保证父进程调节偏移量成功
  41.  
  42. //从用户角度去看,子进程会复制一份父进程的文件描述符,都指向同一个文件
  43. //从内核角度区看,文件描述符表复制了一份,文件描述符表指向了同一个文件表项,都指向同一个文件
  44. //此处的 fd 是从父进程中复制过来的
  45. //但和父进程中的 fd 都是指向同一个文件的
  46. if(write(fd, str, size) != size) {
  47. perror("write error");
  48. exit();
  49. }
  50. }
  51.  
  52. printf("pid ; %d finish\n", getpid());
  53. sleep();
  54.  
  55. //父子进程都要去关闭文件描述符
  56. close(fd);
  57.  
  58. return ;
  59. }

  编译运行:

  

  

二十二、Linux 进程与信号---进程创建(续)的更多相关文章

  1. Linux学习之CentOS(二十六)--Linux磁盘管理:LVM逻辑卷的创建及使用

    在上一篇随笔里面 Linux学习之CentOS(二十五)--Linux磁盘管理:LVM逻辑卷基本概念及LVM的工作原理,详细的讲解了Linux的动态磁盘管理LVM逻辑卷的基本概念以及LVM的工作原理, ...

  2. JAVA基础知识总结:一到二十二全部总结

    >一: 一.软件开发的常识 1.什么是软件? 一系列按照特定顺序组织起来的计算机数据或者指令 常见的软件: 系统软件:Windows\Mac OS \Linux 应用软件:QQ,一系列的播放器( ...

  3. 智课雅思词汇---二十二、-al即是名词性后缀又是形容词后缀

    智课雅思词汇---二十二.-al即是名词性后缀又是形容词后缀 一.总结 一句话总结: 后缀:-al ②[名词后缀] 1.构成抽象名词,表示行为.状况.事情 refusal 拒绝 proposal 提议 ...

  4. [分享] IT天空的二十二条军规

    Una 发表于 2014-9-19 20:25:06 https://www.itsk.com/thread-335975-1-1.html IT天空的二十二条军规 第一条.你不是什么都会,也不是什么 ...

  5. Bootstrap <基础二十二>超大屏幕(Jumbotron)

    Bootstrap 支持的另一个特性,超大屏幕(Jumbotron).顾名思义该组件可以增加标题的大小,并为登陆页面内容添加更多的外边距(margin).使用超大屏幕(Jumbotron)的步骤如下: ...

  6. Web 前端开发精华文章推荐(HTML5、CSS3、jQuery)【系列二十二】

    <Web 前端开发精华文章推荐>2014年第一期(总第二十二期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML ...

  7. 二十二、OGNL的一些其他操作

    二十二.OGNL的一些其他操作 投影 ?判断满足条件 动作类代码: ^ $   public class Demo2Action extends ActionSupport {     public ...

  8. WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇]

    原文:WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇] 在[上篇]中,我们分别站在消息交换和编程的角度介绍了SOAP Fault和FaultException异常.在服务执行过 ...

  9. VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池

    VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池 在上一节我们创建了完整克隆的自动专有桌面池,在创建过程比较缓慢,这次我们将学习创建Vi ...

  10. Bootstrap入门(二十二)组件16:列表组

    Bootstrap入门(二十二)组件16:列表组 列表组是灵活又强大的组件,不仅能用于显示一组简单的元素,还能用于复杂的定制的内容. 1.默认样式列表组 2.加入徽章 3.链接 4.禁用的列表组 5. ...

随机推荐

  1. apache ArrayUtils 工具类

    org.apache.commons.lang3.ArrayUtils // 1.add():将给定的数据添加到指定的数组中,返回一个新的数组. int[] arr = { 1, 2, 3 }; in ...

  2. WinterAndSnowmen

    https://vjudge.net/problem/TopCoder-12891 暴力想法是:dp[i][s1][s2]前i个,第一个集合xor是s1,第二个集合xor是s2方案数O(n^3) 有x ...

  3. 遍历HTML DOM 树

    <!-- NodeIterator --> <!DOCTYPE html> <html> <head> <meta charset="u ...

  4. 【css技能提升】完美的 Sticky Footer 布局

    在总结之前所做的项目时,遇到过下面这种情况. 在主体内容不足够多或者未完全加载出来之前,就会导致出现左边的这种情况,原因是因为没有足够的垂直空间使得页脚推到浏览器窗口最底部.但是,我们期望的效果是页脚 ...

  5. 修改 iis 的端口号: 80 与 443

    来自:https://support.microsoft.com/en-us/help/149605/how-to-change-the-tcp-port-for-iis-services Micro ...

  6. 第二十四篇-用VideoView制作一个简单的视频播放器

    使用VideoView播放视频,视频路径有三种: 1. SD卡中 2. Android的资源文件中 3. 网络视频 第一种,SD卡中的方法. 路径写绝对路径,如果不能播放,可以赋予读取权限. 效果图: ...

  7. django框架中的全文检索Haystack

    1.什么是Haystack Haystack是django的开源全文搜索框架(全文检索不同于特定字段的模糊查询,使用全文检索的效率更高 ),该框架支持Solr,Elasticsearch,Whoosh ...

  8. 第十四节、FAST角点检测(附源码)

    在前面我们已经陆续介绍了许多特征检测算子,我们可以根据图像局部的自相关函数求得Harris角点,后面又提到了两种十分优秀的特征点以及他们的描述方法SIFT特征和SURF特征.SURF特征是为了提高运算 ...

  9. HDU 1560 DNA sequence (迭代加深搜索)

    The twenty-first century is a biology-technology developing century. We know that a gene is made of ...

  10. php 在服务器端开启错误日志记录方法

    修改php.ini设置,或者通过方法 ini_set设置以下项即可 1.打开error_reporting设置: 如 error_reporting= E_ALL 2.  log_errors=On ...