Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15174
  • 博文数量: 6
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 71
  • 用 户 组: 普通用户
  • 注册时间: 2017-01-18 15:29
文章分类
文章存档

2017年(6)

我的朋友

分类: LINUX

2017-02-07 16:55:35

00009-linux系统调用(文件操作).doc


几个常用文件编程函数讲解及例程:

常用的系统调用函数有:creat  open close read write iseek

1.     Creat

 

creat(建立文件)

相关函数 read,write,fcntl,close,link,stat,umask,unlink,fopen

表头文件

#include

#include

#include

C语言:#include

定义函数

int creat(const char * pathname, mode_t mode);

函数功能:

创建一个文件并以只写的方式打开。如果原来该文件存在,会将这个文件的长度截短为0。

函数说明

若函数执行成功则返回打开文件的描述符,出错返回-1并设置errno。(关于errno详见《UNIX环境高级编程》第一章第七节)

参数pathname指向欲建立的文件路径字符串。creat()相当于使用下列的调用方式调用open()

open(const char * pathname ,(O_CREAT|O_WRONLY|O_TRUNC));

由于creat函数创建文件后是以只写的方式打开,因此局限性比较大,所以一般都用open函数来代替creat函数创建一个文件,这样创建后就能同时以读写的方式打开文件了。

关于参数mode请参考《UNIX环境高级编程》第四章。

历史原因

提供creat函数是由于早期的UNIX系统版本中,open的第二个参数只能是0、1、2,没有办法打开一个尚未存在的文件,因此需要另一个creat以创建新文件。

返回值

creat()会返回新的,若有错误发生则会返回-1,并把设给errno。

EEXIST 参数pathname所指的文件已存在。

EACCESS 参数pathname 所指定的文件不符合所要求测试的权限

EROFS 欲打开写入权限的文件存在于只读文件系统内

EFAULT 参数pathname 指针超出可存取的内存空间

EINVAL 参数mode 不正确。

ENAMETOOLONG 参数pathname太长。

ENOTDIR 参数pathname为一目录

ENOMEM 核心内存不足

ELOOP 参数pathname有过多符号连接问题。

EMFILE 已达到进程可同时打开的文件数上限

ENFILE 已达到系统可同时打开的文件数上限

附加说明

creat()无法建立特别的装置文件,如果需要请使用mknod()。

     例子:



通过运行结果可以看出成功建立xinyu_share文件。

2.     Open

 

作用:和创建文件。

简述:open是UNIX系统(包括LINUX、Mac等)的系统调用函数,区别于C语言库函数fopen。

#include

int open(constchar*pathname,intflags);

int open(constchar*pathname,intflags,mode_tmode);

返回值:成功则返回文件描述符,否则返回-1

对于open函数来说,第三个参数仅当创建新文件时(即 使用了O_CREAT 时)才使用,用于指定文件的访问权限位(access permission bits)。pathname 是待/创建文件的POSIX路径名(如/home/user/a.cpp);flags 用于指定文件的打开/创建模式,这个参数可由以下(定义于)通过逻辑位或逻辑构成。

O_RDONLY只读模式

O_WRONLY只写模式

O_RDWR读写模式

打开/创建文件时,至少得使用上述三个常量中的一个。以下常量是选用的:

O_APPEND每次写操作都写入文件的末尾

O_CREAT如果指定文件不存在,则创建这个文件

O_EXCL如果要创建的文件已存在,则返回-1,并且修改errno的值

O_TRUNC如果文件存在,并且以只写/读写方式打开,则清空文件全部内容(即将其长度截短为0)

O_NOCTTY如果路径名指向终端设备,不要把这个设备用作控制终端。

O_NONBLOCK如果路径名指向FIFO/块文件/字符文件,则把文件的打开和后继I/O

设置为非阻塞模式

nonblockingmode

以下三个常量同样是选用的,它们用于同步输入输出

O_DSYNC等待物理I/O结束后再write。在不影响读取新写入的数据的

前提下,不等待

文件属性

更新。

O_RSYNCread等待所有写入同一区域的写操作完成后再进行

O_SYNC等待物理I/O结束后再write,包括更新文件属性的I/O

open返回的一定是最小的未被使用的描述符。

 

3.     Close

 

头文件:#include
定义函数:int close(int fd);
函数说明:当使用完文件后若已不再需要则可使用 close()关闭该文件, close()会让数据写回磁盘, 并释放该文件所占用的资源. 参数fd 为先前由open()creat()所返回的文件描述词.

4.     Read

 

ssize_t read[1]  (int fd, void *buf, size_t count);

返回值

成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0。

参数

参数count是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移。注意这个读写位置和使用C标准I/O库时的读写位置有可能不同,这个读写位置是记在内核中的,而使用C标准I/O库时的读写位置是用户空间I/O缓冲区中的位置。比如用fgetc读一个字节,fgetc有可能从内核中预读1024个字节到I/O缓冲区中,再返回第一个字节,这时该文件在内核中记录的读写位置是1024,而在FILE结构体中记录的读写位置是1。注意返回值类型是ssize_t,表示有符号的size_t,这样既可以返回正的字节数、0(表示到达文件末尾)也可以返回负值-1(表示出错)。

read函数返回时,返回值说明了buf中前多少个字节是刚读上来的。有些情况下,实际读到的字节数(返回值)会小于请求读的字节数count,例如:读常规文件时,在读到count个字节之前已到达文件末尾。例如,距文件末尾还有30个字节而请求读100个字节,则read返回30,下次read将返回0。

 

5.     Write

 

表头文件

#include

定义函数

s write (int fd,const void * buf,size_t count);

函数说明

write()会把指针buf所指的内存写入count个字节到参数fd所指的文件内。当然,文件读写位置也会随之移动。

返回值

如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,存入errno中。

错误代码

EINTR 此调用被信号所中断。

EAGAIN 当使用不可阻断I/O 时(O_NONBLOCK),若无数据可读取则返回此值。

EBADF 参数fd非有效的,或该文件已关闭。

 

6.     Iseek

 

函数名: lseek

头文件:#include #include

用 法: off_t lseek(int handle, off_t offset, int fromwhere);

所有打开的文件都有一个(current file offset),以下简称为 cfo。cfo 通常是一个非负整数,用于表明文件开始处到文件当前位置的字节数。读写操作通常开始于 cfo,并且使 cfo 增大,增量为读写的字节数。文件被打开时,cfo 会被初始化为 0,除非使用了 O_APPEND 。

使用 lseek 函数可以改变文件的 cfo 。

lseek 的以下用法返回当前的偏移量:

off_t currpos;

currpos = lseek(fd, 0, SEEK_CUR);

这个技巧也可用于判断我们是否可以改变某个文件的。如果参数 fd()指定的是 pipe(管道)、FIFO 或者 socket,lseek 返回 -1 并且置 errno 为 ESPIPE。

对于普通文件(regular file),cfo 是一个非负整数。但对于特殊设备,cfo 有可能是负数。因此,我们不能简单地测试 lseek 的返回值是否小于 0 来判断 lseek 成功与否,而应该测试 lseek 的返回值是否等于 -1 来判断 lseek 成功与否。

lseek 仅将 cfo 保存于中,不会导致任何 I/O 操作。这个 cfo 将被用于之后的读写操作。

如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重复的 0 表示。空洞是否占用硬盘空间是由文件系统(file system)决定的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

综合例子:


LINUX下手动建立文件file_from并在文件中随便输入一些内容如图



编译程序并运行可以发现当前目录下生成了一个file_to文件,打开这个文件,里面的内容跟file_from中的完全一样,这就是这个例子实现的文件复制功能。

阅读(1092) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~