Linux程序设计笔记(第3章 文件操作)

    Linux中,一切都是文件。磁盘文件、目录、打印机、用户终端和其他设备等,在Linux看来都是文件。大多数情况下,对这些文件的操作只需要使用5个基本函数:openreadwritecloseioctl

针对输入输出操作直接使用底层系统调用有一个问题是效率非常低下。原因有两个,

其一,系统调用会带来linux从用户态到内核态的来回切换的开销,以致影响了系统的性能。其二,硬件会限制对底层系统调用一次所能读写的数据块大小。

为了给设备和磁盘文件提供更高层的接口,Linux发行版提供了一系列的标准函数库。其中,提供了输出缓冲功能的标准I/O库,我们可以高效地写任意长度的数据块,库函数则在数据满足数据块长度要求时安排执行底层系统调用,从而减少系统调用带来的开销。

   

    系统调用函数原型及其功能说明:

open

头文件:#include <fcntl.h>

原型:int open(char *name, int flags, int perms);

功能:打开文件或设备

返回:成功返回文件描述符;失败返回-1并设置全局变量errno

close

头文件:#include <unistd.h>

原型:int close(int fildes);

功能:关闭文件或设备,即终止文件描述符fildes与其对应文件之间的关联。

返回:成功返回0;出错返回-1

write

头文件:#include <unistd.h>

原型:size_t write(int fildes, const void *buf, size_t nbytes);

功能:向文件或设备写数据,即把缓冲区buf的前nbytes个字节写入与文件描述符fildes关联的文件中。

返回:实际写入的字节数

read

头文件:#include <unistd.h>

原型:size_t read(int fildes, void *buf, size_t nbytes);

功能:从打开的文件或设备里读数据,即从与文件描述符fildes相关联的文件里读入nbytes个字节的数据,并把它们放到数据区buf中。

返回:实际读入的字节数

ioctl

头文件:#include <unistd.h>

原型:int ioctl(int fildes, int cmd, …);

功能:把控制信息传递给设备驱动程序,即对文件描述符fildes引用的对象执cmd参数中给出的操作。

系统调用ioctl用于提供一些与特定硬件设备有关的必要控制(与正常的输入输出相反),所以它的用法随设备的不同而不同。如,ioctl调用可以用于回绕磁带机或设置串行口的流控特性。因此,ioclt并不需要具备可移植性。每个驱动程序都定义了它自己的一组ioctl命令。

返回:成功回0;失败返回-1 

lseek

头文件:#include <unistd.h> #include <sys/types.h>

原型:off_t lseek(int fildes, off_t offset, int whence);

功能:对文件描述符fildes的读写指针进行设置。

返回:成功返回从文件头到文件指针被设置处的字节偏移值;失败返回-1

fstat

头文件:#include <unistd.h> #include <sys/stat.h>

原型:int fstat(int fildes, struct stat *buf);

功能:通过文件描述符获取文件状态信息

返回:成功返0;失败返回-1,并设置全局变量errno

stat

头文件:#include <unistd.h> #include <sys/stat.h>

原型:int stat(const char *path, struct stat *buf);

功能:通过文件名获取文件状态信息,当文件是一个符号链接时,返回该链接指向的文件的信息。

返回:成功返回0;失败返回-1,并设置全局变量errno

lstat

头文件:#include <unistd.h> #include <sys/stat.h>

原型:int lstat(const char *path, struct stat *buf);

功能:通过文件名获取文件状态信息,当文件是一个符号链接时,返回该链接本身的信息。

返回:成功返回0;失败返回-1,并设置全局变量errno

dup

dup2

头文件:#include <unistd.h>

原型:int dup(int fildes);

int dup2(int fildes, int fildes2);

功能:dup系统调用提供了一种复制文件描述符的方法,使我们能够通过两个或者更 

     多个不同的描述符来访问同一个文件。这可以用于在文件的不同的位置对数据

     进行读写。

返回:dup返回一个新的文件描述符;dup2返回指定的目标文件描述符fildes2

fcntl

头文件:#include <fcntl.h>

原型:int fcntl(int fildes, int cmd);

     int fcntl(int fildes, int cmd, long arg);

功能:利用fcntl系统调用,可以对打开的文件描述符执行各种操作,包括对它们进行赋值、获取和设置文件描述符标志、获取和设置文件状态标志,以及管理建议性文件锁等。

返回:成功返回相应的值;失败返回-1

mmap

头文件:#include <sys/mman.h>

原型:void *mmap(void *addr, size_t len, int prot, int flags,

              int fildes, off_t off);

功能:建立一段可以被两个或更多程序读写的内存,一个程序对它所做出的修改可以被其他程序看见。

返回:成功返回指向映射区的指针,失败返回MAP_FAILED并设置errno的值


    启动一个C语言程序时,操作系统环境负责打开3个文件,并将这3个文件的指针提供给该程序。这3个文件分别是标准输入、标准输出和标准错误,相应个文件指针分别为stdinstdoutstderr

    当shell运行一个程序时,它将打开3个文件,即标准输入、标准输出和标准错误,对应的文件描述符分别是012.除了默认的标准输入、标准输出和标准错误文件外,其他文件都必须在读或写之前显示地打开。

文件描述符(int

文件指针(FILE *

文件

0

stdin

标准输入

1

stdout

标准输出

2

stderr

标准错误


库函数与系统调用

库函数

系统调用

fopen

open

fwrite

write

fread

read

fclose

close

fseek

lseek

fgetcgetcgetchar

fstat

fputcputcputchar

stat

fgetsfputs

lstat

fflushferrorfeof

 

fgetposfsetposftellrewindfreopensetvbufremove

 

 

  全局变量errno在头文件errno.h中定义,以下的错误代码包括其取值及定义摘自头文件errno-base.h

#define EPERM        1  /* Operation not permitted */
#define ENOENT       2  /* No such file or directory */
#define ESRCH        3  /* No such process */
#define EINTR        4  /* Interrupted system call */
#define EIO          5  /* I/O error */
#define ENXIO        6  /* No such device or address */
#define E2BIG        7  /* Argument list too long */
#define ENOEXEC      8  /* Exec format error */
#define EBADF        9  /* Bad file number */
#define ECHILD      10  /* No child processes */
#define EAGAIN      11  /* Try again */
#define ENOMEM      12  /* Out of memory */
#define EACCES      13  /* Permission denied */
#define EFAULT      14  /* Bad address */
#define ENOTBLK     15  /* Block device required */
#define EBUSY       16  /* Device or resource busy */
#define EEXIST      17  /* File exists */
#define EXDEV       18  /* Cross-device link */
#define ENODEV      19  /* No such device */
#define ENOTDIR     20  /* Not a directory */
#define EISDIR      21  /* Is a directory */
#define EINVAL      22  /* Invalid argument */
#define ENFILE      23  /* File table overflow */
#define EMFILE      24  /* Too many open files */
#define ENOTTY      25  /* Not a typewriter */
#define ETXTBSY     26  /* Text file busy */
#define EFBIG       27  /* File too large */
#define ENOSPC      28  /* No space left on device */
#define ESPIPE      29  /* Illegal seek */
#define EROFS       30  /* Read-only file system */
#define EMLINK      31  /* Too many links */
#define EPIPE       32  /* Broken pipe */
#define EDOM        33  /* Math argument out of domain of func */
#define ERANGE      34  /* Math result not representable */
<span style="font-family:KaiTi_GB2312;">
</span>
    许多系统调用和库函数在调用失败时都会设置全局变量errno的值来指明失败的原因。有两个函数可以用来报告出现的错误:

<span style="font-family:KaiTi_GB2312;font-size:14px;">#include <string.h>
原型:char *strerror(int errnum);
功能:把错误代码映射为一个字符串,该字符串对发生的错误类型进行说明。
</span>
<span style="font-family:KaiTi_GB2312;font-size:14px;">#include <stdio.h>
原型:void perror(const char *s);
功能:将你输入的一些信息和现在errno所对应的错误一起输出。
</span>




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值