unix环境高级编程第三章笔记
文件描述符
1、文件描述符的概念
对于内核而言,所有打开的文件都会用一个文件描述符来引用,打开或和创建一个新文件的时候,内核会给进程返回一个文件描述符,而当使用read write时,可以使用这个文件描述符来代替文件。
UNIX系统下,使用0 1 2 来分别与标准输入 标准输出 标准出错输出相关联。
2、文件操作有关的函数
open函数
/*fcntl.h定义了很多宏和fcntl函数原型*/
#include <fcntl.h>
int open(const char *pathname ,int oflag,/*mode_t mode*/);
/*例子*/
int fd = open("a.txt",O_RDONLY)
if(fd ==-1)
return -1;
函数的参数:
pathname:需要打开或者创建文件的路径
oflag:此参数的多个选项
mode:当oflag = O_CREAT 时,需要额外指定的参数,用来表示新创建文件的访问权限位如0777
函数的返回值:
成功返回文件描述符,失败返回 -1
oflag可选的选项:
O_APPEND 每次写都追加到文件的末端
O_CREAT 如果文件不存在就创建一个
O_TRUNC 如果此文件存在而且是以读和写的形式打开,就把他的文件长度截断到0
O_DSYNC 使每次write等待物理io操作完成,但是如果写操作不影响读取则不等待
O_RSYNC 让每一个read操作等待,直到对文件同一部分的写操作完成
O_RDONLY O_WRONLY O_RDWR 只读打开 只写打开 读写打开
open返回的文件描述符一定是最小的文件描述符
close函数
#include<unistd>
int close(int fd);
返回值:
成功返回0,失败返回-1
关闭一个文件还会清除这个文件的记录锁
当一个进程终止时,内核会自动关闭进程打开的文件
lseek函数
每个打开的文件都有其文件偏移量,通常是一个非负数,读写操作都会从这个当前偏移量开始,每读或者写一字节,文件偏移量后移一字节
#include<unist.h>
off_t lseek (int fd, off_t offset,int whence);
参数:
fd: 需要被修改文件偏移量的文件描述符
whence:SEEK_SET 文件偏移量设为距离文件开始处offset字节
SEEK_CUE 文件偏移量设为当前值处offset字节
SEEK_END 文件偏移量设为距离文件末尾处offset字节
返回值:
成功返回新的文件偏移量,出错就返回 -1
如果文件描述符引用的是一个管道 FIFO或网络套接字,lseek返回-1,并将errno设置为ESPIPE
lseek把当前文件的偏移量记录在内核,不会引起io操作
#include<fcntl>
#include"apue.h"
char buf[] = "asdfg"
char buf[] = "ASDFG"
int main ()
{
int fd;
if ((fd = open ("a.txt",O_WDWR | O_CREAT,FILE_MODE))<0)
err_sys("creat err");
if(write(fd,buff1, 5) != 5)
err_sys("buff1 write err");
/*会制造一个空洞*/
if(lseek(fd,10 ,SEEK_SET) == -1)
err_sys ("lseek err ");
if(write(fd,buff2, 5) != 5)
err_sys("buff2 write err");
exit(0);
}
read函数
调用read可以从打开的文件中读取数据
#include <unistd.h>
ssize_t read(int fd , void *buff ,size nbyte);
参数:
fd:文件描述符
buff:文件要读到哪里去
nbyte:文件要读多少字节
返回值:
读取成功则返回读取的字符,失败就返回-1
当没有读完要求的字节就已经到达文件末尾,直接返回已经读取的文件数。此时文件偏移量在末尾,继续调用read只会返回0
write函数
调用write函数向打开的文件写数据
#include<unistd.h>
size_t write(int fd , const void *buff ,size nbyte);
参数:
fd:文件描述符
buff:文件要把哪里的数据写入
nbyte:文件要写多少字节
返回值:
写入成功就返回已经写入的字节数,失败就返回-1
返回值一般要和 nbyte 相同,不然就显示出错,出错的原因一般是:磁盘已经写满,超过了一个给定进程的文件长度限制
io的效率
#include "apue.h"
#define BUFFSIZE 4096
int
main(void)
{
int n;
char buf[BUFFSIZE];
while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
if (write(STDOUT_FILENO, buf, n) != n)
err_sys("write error");
if (n < 0)
err_sys("read error");
exit(0);
}
上述函数把标准输入复制到标准输出,但对于不同的BUFFSIZE,程序运行的时间是不一样的
一般来讲,系统cpu时间随着BUFFSIZE的增大而减小(越来越快),而最大值出现在4096,继续增大不会对系统cpu时间产生更大的影响
文件共享
内核用三种数据结构来表示打开的文件:
- 每个进程都会在进程表中有一个记录项,记录项中包含有一张这个进程打开的文件表,文件表中每一项包含文件描述符,和一个指向文件表项的指针
- 内核为所有已经打开的文件维持了一个文件表,每个文件表项包括:文件状态标志 当前文件偏移量 指向该文件v节点表项的指针
- v节点表项包含了v节点信息 i节点信息 当前文件长度

如果有两个独立进程各自打开了同一个文件,打开该文件的每一个进程都会得到一个文件表项:每个进程都有独立的文件偏移量
每个文件都只有一个v节点表项
也有共享同一个文件表项的情况:fork()之后的父子进程
原子操作
原子操作是独立的一个个体,要么全都完成,要么一点都不做。
dup和dup2函数
#include<unist.h>
int dup(int fd);
int dup(int oldfd,int newfd);
dup函数:内核在进程中创建一个新的文件描述符,此描述符是当前可用文件描述符的最小数值,这个文件描述符指向oldfd所拥有的文件表项。
dup2函数:用newfd参数指定新描述符的数值,如果newfd已经打开,则先将其关闭。如果newfd等于oldfd,则dup2返回newfd, 而不关闭它。dup2函数返回的新文件描述符同样与参数oldfd共享同一文件表项。
sync fsync fdatasync函数
unix内核也存在一块缓冲区,被称为update的系统守护进程会周期性的调用sync,当数据写入文件时,内核把数据复制到其中一个缓冲区,如果该缓冲区满了,派入输出队列,没有满则等待
#incude<unist.h>
/*把所有修改过的块缓冲区送到队列,不等待写磁盘操作结束*/
void sync;
/*只对单一文件有效果,等待写磁盘操作结束*/
int fsync(int fd);
/*只对数据有效,其他同fsync*/
int fdatasync(int fd);
/dev/fd
打开/dev/fd/n 和复制描述符n等效。
unix环境高级编程第三章笔记的更多相关文章
- UNIX环境高级编程-第三章习题
1,当读写磁盘文件时,read,write等函数确实是不带缓冲机制的吗?请说明原因. 答:所有磁盘I/O都要经过内核的块缓存区(即内核的缓冲区高速缓存).唯一例外的是对原始磁盘设备的I/O,但是我们不 ...
- unix环境高级编程第六章笔记
口令文件 阴影口令 组文件 附属组ID 登录账户记录 系统标识 口令文件<\h2> /etc/passwd文件是UNIX安全的关键文件之一.该文件用于用户登录时校验用户的口令,文件中每行的 ...
- unix环境高级编程第四章笔记
文件和目录 start fstart lstart函数 一旦给出pathname, start函数就返回了与此命名文件有关的信息结构 #include <sys/start> int st ...
- 【转】apue《UNIX环境高级编程第三版》第一章答案详解
原文网址:http://blog.csdn.net/hubbybob1/article/details/40859835 大家好,从这周开始学习apue<UNIX环境高级编程第三版>,在此 ...
- Linux - Unix环境高级编程(第三版) 代码编译
Unix环境高级编程(第三版) 代码编译 本文地址:http://blog.csdn.net/caroline_wendy 时间:2014.10.2 1. 下载代码:http://www.apuebo ...
- Unix环境高级编程第三版中实例代码如何在自己的linux上运行的问题
学习Linux已经有2个月了,最近被期末考试把进度耽误了,前几天把Unix环境高级编程看了两章,感觉对Linux的整体有了一些思路,今天尝试着对第一章涉及到的一个简单的交互式shell编译运行一下,结 ...
- UNIX环境高级编程 第8章 进程控制
本章是UNIX系统中进程控制原语,包括进程创建.执行新程序.进程终止,另外还会对进程的属性加以说明,包括进程ID.实际/有效用户ID. 进程标识 每个进程某一时刻在系统中都是独一无二的,它们之间是用一 ...
- UNIX环境高级编程 第7章 进程环境
本章涉及C/C++程序中main函数是如何被调用的.命令行参数如何传递给main函数.程序的内存空间布局.程序如何使用环境变量.程序如何终止退出. main函数 C程序或C++程序总是从main函数开 ...
- UNIX环境高级编程 第4章 文件和目录
第三章说明了关于文件I/O的基本函数,主要是针对普通regular类型文件.本章描述文件的属性,除了regular文件还有其他类型的文件. 函数stat.fstat.fstatat和lstat sta ...
随机推荐
- 使用sublime text3搭建Python编辑环境
最近在工作遇到一个难题. 我所在的测试组有一套PC软件前端自动化工程,在进行自动化测试时,需要在一台古老的xp机器上运行,但这台古老的xp机器带给我诸多烦恼,特别是使用Pycharm编辑器时,我遇到了 ...
- VMware 16.1虚拟机安装
VMware 16.1创建虚拟机 1.1首先打开我们安装好的VMware点击创建新的虚拟机 典型为自动安装,接口位默认 自定义安装更自由,可以把按需求选择 VMware16版本,只能选择Worksta ...
- 值得推荐的C#不同版本语言特性
C#语言在不断地版本升级中,为我们提供了很多新的语言特性.其中,有很多使用的语言特性,我觉得在实际开发中用起来很方便,能够简化我们的代码,增强可读性,提高开发效率. 小编不才,在这里给大家整理了一些实 ...
- es6 Array.from + new Set 去重复
// es6 set数据结构 生成一个数据集 里面的元素是唯一的 const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]); // items 是个对象 item ...
- python模块详解 | selenium(持续更新中)
目录: 关于selenium Selenium 安装Selenium 安装浏览器驱动 配置环境变量 selenium方法详解 定位元素 元素操作 浏览器操作 鼠标事件 浏览器事件 设置元素等待 多表单 ...
- spring boot gateway 过滤器的执行顺序
前言 学习官方文档,发现对于过滤器有分为三类 默认过滤器 自定义过滤 全局过滤器 于是就有一个疑问,关于这些过滤器的访问顺序是怎样的,今天就以一个demo来进行测试 准备阶段 过滤器工厂类 以此为模板 ...
- FlatBuffers使用小结
最近做一个Android APP,由于离线业务需求,需要在启动APP时候同步大量数据到APP上,遇到了JSON性能瓶颈.从下方的图片中可以看出,当使用 json 传输数据,在解析json的时候会产生大 ...
- CTFHub - Web(五)
eval执行: 1.进入网页,显示源码, <?php if (isset($_REQUEST['cmd'])) { eval($_REQUEST["cmd"]); } els ...
- canvas性能-drawImage渲染图片
canvas性能-绘制图片 目录 canvas性能-绘制图片 canvas绘制图片 drawImage putImageData createPattern 测试绘制耗时 drawImage Imag ...
- Visual Studio中自定义代码段!
Visual Studio中自定义代码段! 第一步:在编辑器中进行快捷键的输入[ctrl + shift + p] 或者 点击 查看 第一个选项就是!请看下图 第二步:选择你要配置代码段的语言, 这里 ...