您的位置:首页 > 运维架构 > Linux

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

2014-07-24 22:17 162 查看
   
在Linux中,一切都是文件。磁盘文件、目录、打印机、用户终端和其他设备等,在Linux看来都是文件。大多数情况下,对这些文件的操作只需要使用5个基本函数:open、read、write、close及ioctl。

针对输入输出操作直接使用底层系统调用有一个问题是效率非常低下。原因有两个,
其一,系统调用会带来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个文件分别是标准输入、标准输出和标准错误,相应个文件指针分别为stdin、stdout和stderr。

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

文件描述符(int)

文件指针(FILE *)

文件

0

stdin

标准输入

1

stdout

标准输出

2

stderr

标准错误

库函数与系统调用

库函数

系统调用

fopen

open

fwrite

write

fread

read

fclose

close

fseek

lseek

fgetc、getc、getchar

fstat

fputc、putc、putchar

stat

fgets、fputs

lstat

fflush、ferror、feof

 

fgetpos、fsetpos、ftell、rewind、freopen、setvbuf、remove

 

 
  全局变量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>



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  open perror