二十二、Linux 进程与信号---进程创建(续)
22.2 父子进程操作文件
文件操作由两种模式:
IO 系统调用操作文件
标准C IO 操作文件
看代码:
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h> int g_val = ;//全局变量,存放在数据段 int main(void)
{
int a_val = ;//局部变量,调用的时候存放在栈中
static int s_val = ;//静态变量,存放在数据段
printf("pid: %d", getpid()); FILE *fp = fopen("s.txt", "w");
int fd = open("s_fd.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG); char *s = "hello world";
ssize_t size = strlen(s) * sizeof(char); /* fork 之前,为父进程调用 */
fprintf(fp, "s: %s, pid: %d\n", s, getpid());//标准 IO 写入(带缓存),针对文件操作的是全缓存
write(fd, s, size); //内核提供的 IO 系统调用(不带缓存) pid_t pid;
pid = fork();//创建子进程
//在 fork 后,会运行两个进程(父进程和子进程)
if(pid < ) {
perror("fork error");
} else if(pid > ) {
//父进程(在父进程中返回的是子进程的 pid)
//父进程执行的代码
g_val = ;
a_val = ;
s_val = ; printf("I am parent process pid is %d, ppid is %d, fork return is %d\n",
getpid(), getppid(), pid);
printf("g_val: %p, a_val: %p, s_val: %p\n", &g_val, &a_val, &s_val);
} else {
//子进程(在子进程中 fork 返回的是0)
//子进程执行的代码
g_val = ;
a_val = ;
s_val = ;
printf("I am child process pid is %d, ppid is %d, fork return is %d\n",
getpid(), getppid(), pid);
printf("g_val: %p, a_val: %p, s_val: %p\n", &g_val, &a_val, &s_val);
} //这里的代码是父子进程都要执行的代码,写入父子进程各自的缓存当中
fprintf(fp, " pid: %d, g_val: %d, a_val: %d, s_val: %d\n", getpid(), g_val, a_val, s_val);
sleep(); return ;
}
编译运行后,两个文件都生成了。

父进程文件 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
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> int main(int argc, char *argv[])
{
if(argc < )
{
fprintf(stderr, "usage: %s file\n", argv[]);
exit();
} int fd = open(argv[], O_WRONLY);
if(fd < )
{
perror("open error");
exit();
} pid_t pid = fork();
if(pid < )
{
perror("fork error");
exit();
}
else if(pid > )
{//父进程将文件偏移量调整到文件尾部
if(lseek(fd, 0L, SEEK_END) < ) {
perror("lseek error");
exit();
}
}
else
{//子进程从文件尾部追加内容
char *str = "hello child";
ssize_t size = strlen(str) * sizeof(char); sleep();//保证父进程调节偏移量成功 //从用户角度去看,子进程会复制一份父进程的文件描述符,都指向同一个文件
//从内核角度区看,文件描述符表复制了一份,文件描述符表指向了同一个文件表项,都指向同一个文件
//此处的 fd 是从父进程中复制过来的
//但和父进程中的 fd 都是指向同一个文件的
if(write(fd, str, size) != size) {
perror("write error");
exit();
}
} printf("pid ; %d finish\n", getpid());
sleep(); //父子进程都要去关闭文件描述符
close(fd); return ;
}
编译运行:


二十二、Linux 进程与信号---进程创建(续)的更多相关文章
- Linux学习之CentOS(二十六)--Linux磁盘管理:LVM逻辑卷的创建及使用
在上一篇随笔里面 Linux学习之CentOS(二十五)--Linux磁盘管理:LVM逻辑卷基本概念及LVM的工作原理,详细的讲解了Linux的动态磁盘管理LVM逻辑卷的基本概念以及LVM的工作原理, ...
- JAVA基础知识总结:一到二十二全部总结
>一: 一.软件开发的常识 1.什么是软件? 一系列按照特定顺序组织起来的计算机数据或者指令 常见的软件: 系统软件:Windows\Mac OS \Linux 应用软件:QQ,一系列的播放器( ...
- 智课雅思词汇---二十二、-al即是名词性后缀又是形容词后缀
智课雅思词汇---二十二.-al即是名词性后缀又是形容词后缀 一.总结 一句话总结: 后缀:-al ②[名词后缀] 1.构成抽象名词,表示行为.状况.事情 refusal 拒绝 proposal 提议 ...
- [分享] IT天空的二十二条军规
Una 发表于 2014-9-19 20:25:06 https://www.itsk.com/thread-335975-1-1.html IT天空的二十二条军规 第一条.你不是什么都会,也不是什么 ...
- Bootstrap <基础二十二>超大屏幕(Jumbotron)
Bootstrap 支持的另一个特性,超大屏幕(Jumbotron).顾名思义该组件可以增加标题的大小,并为登陆页面内容添加更多的外边距(margin).使用超大屏幕(Jumbotron)的步骤如下: ...
- Web 前端开发精华文章推荐(HTML5、CSS3、jQuery)【系列二十二】
<Web 前端开发精华文章推荐>2014年第一期(总第二十二期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML ...
- 二十二、OGNL的一些其他操作
二十二.OGNL的一些其他操作 投影 ?判断满足条件 动作类代码: ^ $ public class Demo2Action extends ActionSupport { public ...
- WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇]
原文:WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇] 在[上篇]中,我们分别站在消息交换和编程的角度介绍了SOAP Fault和FaultException异常.在服务执行过 ...
- VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池
VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池 在上一节我们创建了完整克隆的自动专有桌面池,在创建过程比较缓慢,这次我们将学习创建Vi ...
- Bootstrap入门(二十二)组件16:列表组
Bootstrap入门(二十二)组件16:列表组 列表组是灵活又强大的组件,不仅能用于显示一组简单的元素,还能用于复杂的定制的内容. 1.默认样式列表组 2.加入徽章 3.链接 4.禁用的列表组 5. ...
随机推荐
- Nginx log日志切割shell
#!/bin/bash#此脚本用于自动分割Nginx的日志,包括access.log和error.log#每天00:00执行此脚本 将前一天的access.log重命名为access-xxxx-xx- ...
- print
说一说这个print函数,我们经常使用,但有一些细节却往往错过了 print print()输出会换行是因为默认end="\n" 想要不换行,且覆盖 print("\r第 ...
- 2019 校内赛 RPG的地牢猎手(bfs+优先队列)
Problem Description Luke最近沉迷一款RPG游戏,游戏中角色可以进入地牢关卡,只要顺利走出地牢就可以获得奖励.地牢表示为n行m列的块矩阵,其中每个块只可以是障碍块.入口.出口或数 ...
- 在linux环境下搭建JDK+JAVA+Mysql,并完成jforum的安装
参考链接: YUM安装MySQL和JDK和Tomcat:http://cmdschool.blog.51cto.com/2420395/1696206/ http://www.cnblogs.com/ ...
- 使用Disruptor实现生产者和消费者模型
生产者 package cn.lonecloud.procum.disruptor; import cn.lonecloud.procum.Data; import com.lmax.disrupto ...
- BZOJ 4562: [Haoi2016]食物链(拓扑排序)
题面: https://www.lydsy.com/JudgeOnline/problem.php?id=4562 一句话题意:给一个DAG,求有多少条不完全相同的链,使链首入度为0,链尾出度为0. ...
- 【CF600E】Lomsat gelral
题目大意:给定一棵 N 个节点的有根树,1 号节点是树的根节点,每个节点有一个颜色.求对于每个节点来说,能够支配整棵子树的颜色之和是多少.支配的定义为对于以 i 为根的子树,该颜色出现的次数不小于任何 ...
- 前端模块化,AMD与CMD的区别
最近在研究cmd和amd,在网上看到一篇不错的文章,整理下看看. 在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可:如今CPU.浏览器性能得到了极大的提升,很多页面逻辑迁移到 ...
- 关于MyBase 7.0 破解的方法
Mybase 是一个功能强劲且可随心所欲自定义格式及层次关系的通用资料管理软件, 可用于管理各种各样的信息,如一:各类文档.文件.资料.名片.事件.日记.项目.笔记.下载的精华.收集的各种资料等等,即 ...
- python正则提取关键字
python使用正则表达式提取关键字 import sys reload(sys) sys.setdefaultencoding("utf-8") import re ss = & ...