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 ...
随机推荐
- 免费、开源的基于tp5的快速开发框架
HisiPHP 系统官网:https://www.hisiphp.com/ 后台体验:http://v2.demo.hisiphp.com/admin.php/system/publics/index ...
- oracle 11.2.0.1.0 升级 11.2.0.4.0 并 patch 到11.2.0.4.7
升级步骤: (1) 备份数据库 (2) 运行patchset,升级oracle 软件 (3) 准备新的ORACLE_HOME (4) 运行dbua 或者脚本升级实例 (5) ...
- python中列表的insert和append的效率对比
python中insert和append方法都可以向列表中插入数据只不过append默认插入列表的末尾,insert可以指定位置插入元素. 我们来测试一下他俩插入数据的效率: 测试同时对一个列表进行插 ...
- HAProxy + keepalived 高可用集群代理
HAProxy + keepalived # 1 安装keepalived: yum install keepalived -y # 2 修改KEEPalived配置文件: vim /etc/keep ...
- (十七)logging模块
logging模块是Python内置的标准模块,主要用于输出运行日志. 简单应用 import logging logging.debug('+++debug+++') logging.info('+ ...
- linux线程库
linux 提供两个线程库,Linux Threads 和新的原生的POSIX线程库(NPTL),linux threads在某些情况下仍然使用,但现在的发行版已经切换到NPTL,并且大部分应用已经不 ...
- 【Oracle】11g direct path read介绍:10949 event、_small_table_threshold与_serial_direct_read
转自刘相兵老师的博文: http://www.askmaclean.com/archives/11g-direct-path-read-10949-_small_table_threshold-_se ...
- 环境变量IFS
环境变量IFS的值是由1个空格.1个制表符.1个换行符依序构成的字符串,也就是" \t\n"字符串. #查看IFS变量值的长度: test ~ # expr length &quo ...
- SAP GUI用颜色区分不同的系统
对于经常打开多个窗口的SAP用户,有时候可能同时登录了生产机.测试机和开发机,为了避免误操作,比如在测试要执行的操作,结果在生产机做了,结果可想而知. 虽然可以通过右下角查看再去判断,但是总是没有通过 ...
- 5V-12V输入输出的限流芯片,可调限至4.8A
可是在输出电压模式:3.6V,5V,12V 在输出3.6V模式:输入电压范围2.5V-4.5V,输入关闭电压5V,限流最大4.8A 在输出5V模式,输入电压范围3.8V-6V,输输入过电压关闭6V,限 ...