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

嵌入式linux文件I/O编程 (open、read、write、lseek、close)

2009-10-26 14:09 706 查看
<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:595.3pt 841.9pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:42.55pt;
mso-footer-margin:49.6pt;
mso-paper-source:0;
layout-grid:15.6pt;}
div.Section1
{page:Section1;}
-->

Linux
提供的虚拟文件系统为多种文件系统提供了统一的接口,Linux
的文件编程有两种途径:基于Linux
系统调用;基于C
库函数。这两种编程所涉及到文件操作有新建、打开、读写和关闭,对随机文件还可以定位。

通常,一个进程打开时,都会打开3
个文件:标准输入、标准输出和标准出错处理。这3
个文件分别对应文件描述符为0
、1
和2
(也就是宏替换STDIN_FILENO
、STDOUT_FILENO
和STDERR_FILENO
)。

一、Linux
系统调用

不带缓存的文件I/O
操作,这里指的不带缓存是指每一个函数只调用系统中的一个函数。主要用到5
个函数:open
、read
、write
、lseek
和close


1
、open
函数语法要点:

所需头文件:#include<sys/types.h>//
提供类型pid_t
的定义

#include<sys/stat.h>

#include<fcntl.h>

函数原型:int open(const char *pathname,flags,int perms)

函数传入值:

path
:被打开文件名(可包括路径名)

flag
:文件打开的方式,参数可以通过“|”
组合构成,但前3
个参数不能互相重合。

O_REONLY
:只读方式打开文件

O_WRONLY
:可写方式打开文件

O_RDWR
:读写方式打开文件

O_CREAT
:如果文件不存在时就创建一个新文件,并用第三个参数为其设置权限。

O_EXCL
:如果使用O_CREAT
时文件存在,则可返回错误信息。这一参数可测试文件是否存在。

O_NOCTTY
:使用本参数时,如文件为终端,那么终端不可以作为调用open
()系统调用的那个进程的控制终端。

O_TRUNC
:如文件已经存在,并且以只读或只写成功打开,那么会先全部删除文件中原因数据。

O+APPEND
:以添加方式打开文件,在打开文件的同时,文件指针指向文件末尾。

perms
:被打开文件的存取权限,为8
进制表示法。

函数返回值:成功:返回文件描述符 失败:-1

2
、Close
语法要点:

所需头文件:#include<uniste.h>

函数原型:int close
(int fd


函数输入值:fd
:文件描述符

函数返回值:成功:0

出错:-1

3
、Read
函数语法要点

所需头文件:#include<unistd.h>

函数原型:ssize_t read(int fd,void *buf,size_t count)

函数传入值

fd:
文件描述符

Buf
:指定存储器读出数据的缓冲区

Count
:指定读出的字节数

函数返回值:成功:读出的字节数 0
:已到达文件尾
-1
:出错

在读普通文件时,若读到要求的字节数之前已达到文件的尾部,则返回字节数会小于希望读出的字节数。

4
、Write
函数语法要点

所需头文件:#include<unistd.h>

函数原型: ssize_t write(int fd,void *buf,size_t
count)

函数传入值:

fd:
文件描述符

Buf
:指定存储器写入数据的缓冲区

Count
:指定读出的字节数

函数返回值:成功:已写的字节数 -1
:出错

5
、Lseek
函数语法要点:

所需头文件:#include<unistd.h>

#include<sys/types.h>

函数原型:off_t lseek(int fd,off_t offset,int whence)

函数传入值:

fd:
文件描述符

Offset
:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负(向前移,向后移)

Whence
:当前位置的基点:

SEEK_SET
:当前位置为文件开头,新位置为偏移量的大小

SEEK_CUR
:当前位置为文件指针位置,新位置为当前位置加上偏移量

SEEK_END
:当前位置为文件的结尾,新位置为文件的大小加上偏移量大小

函数使用实例:

/**/

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

int main(void)

{

char *buf="Hello! I'm writing to this file!";

char buf_r[11];

int fd,size,len;

len = strlen(buf);

buf_r[10] = '/0';

/*

首先调用open
函数,并指定相应的权限*/

if ((fd = open("hello.c", O_CREAT | O_TRUNC |
O_RDWR,0666 ))<0) {

perror("open:");

exit(1);

} else

printf("open and create file:hello.c
%d OK/n",fd);

/*
调用write
函数,将buf
中的内容写入到打开的文件中*/

if ((size = write( fd, buf, len)) < 0){

perror("write:");

exit(1);

} else

printf("Write:%s OK/n",buf);

/*
调用lseek
函数将文件指针移动到文件起始,并读出文件中的10
个字节
*/

lseek(fd, 0, SEEK_SET );

if ((size = read( fd, buf_r, 10))<0) {

perror("read:");

exit(1);

} else

printf("read form file:%s
OK/n",buf_r);

if ( close(fd) < 0 ) {

perror("close:");

exit(1);

} else

printf("Close hello.c OK/n");

return 0;

}

二、C
语言库函数

  C
库函数的文件操作实际上是独立于具体的操作系统平台的,不管是在DOS
、Windows
、Linux
还是在VxWorks
中都是这些函数:

  创建和打开

FILE *fopen(const char *path, const char *mode);

  fopen()
实现打开指定文件filename
,其中的mode
为打开模式,C
语言中支持的打开模式如下表:

标志

含义

r, rb

以只读方式打开

w, wb

以只写方式打开。如果文件不存在,则创建该文件,否则文件被截断

a, ab

以追加方式打开。如果文件不存在,则创建该文件

r+, r+b, rb+

以读写方式打开

w+, w+b, wh+

以读写方式打开。如果文件不存在时,创建新文件,否则文件被截断

a+, a+b, ab+

以读和追加方式打开。如果文件不存在,创建新文件

  其中b
用于区分二进制文件和文本文件,这一点在DOS
、Windows
系统中是有区分的,但Linux
不区分二进制文件和文本文件。

  读写

  C
库函数支持以字符、字符串等为单位,支持按照某中格式进行文件的读写,这一组函数为:

int fgetc(FILE *stream);

int fputc(int c, FILE *stream);

char *fgets(char *s, int n, FILE *stream);

int fputs(const char *s, FILE *stream);

int fprintf(FILE *stream, const char *format, ...);

int fscanf (FILE *stream, const char *format, ...);

size_t fread(void *ptr, size_t size, size_t n, FILE *stream);

size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream);

  fread()
实现从流stream
中读取加n
个字段,每个字段为size
字节,并将读取的字段放入ptr
所指的字符数组中,返回实际已读取的字段 数。在读取的字段数小于num
时,可能是在函数调用时出现错误,也可能是读到文件的结尾。所以要通过调用feof()
和ferror()
来判断。

  write()
实现从缓冲区ptr
所指的数组中把n
个字段写到流stream
中,每个字段长为size
个字节,返回实际写入的字段数。

  另外,C
库函数还提供了读写过程中的定位能力,这些函数包括

int fgetpos(FILE *stream, fpos_t *pos);

int fsetpos(FILE *stream, const fpos_t *pos);

int fseek(FILE *stream, long offset, int whence);

等。

  关闭

  利用C
库函数关闭文件依然是很简单的操作:

int fclose (FILE *stream);

  例程:将第2
节中的例程用C
库函数来实现。

#include <stdio.h>

#define LENGTH 100

main()

{

 FILE *fd;

 char str[LENGTH];

 fd = fopen("hello.txt", "w+"); /*
创建并打开文件 */

 if (fd)

 {

  fputs("Hello, Everyone!", fd); /*
写入Hello,

Everyone!"

字符串 */

  fclose(fd);

 }

 fd = fopen("hello.txt", "r");

 fgets(str, LENGTH, fd); /*
读取文件内容 */

 printf("%s/n", str);

 
fclose(fd);

}

三、

<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->

f c n t l
函数有五种功能:

n

复制一个现存的描述符
,
新文件描述符作为函数值返
(c m d

F_DUPFD
)。

n

获得
/
设置文件描述符标记
,
对应于
filedes

的文件描述符标志作为函数值返回.(
c m d = F_GETFD

F_SETFD
)。

n

获得
/
设置文件状态标志,对应于
filedes

的文件状态标志作为函数值返回。(
c m d = F_GETFL

F_SETFL
)。

n

获得
/
设置异步
I / O
有权(
c
m d = F_GETOWN

F_SETOWN
)。

n

获得
/
设置记录锁(
c m d = F_SETLK , F_SETLKW
)。

#include
<sys/types.h>

#include
<unistd.h>

#include
<fcnt1.h>

int fcnt1(int filedes
,
int cmd
,... struct flock flockptr
) ;

struct flock
结构

ioctl
函数是
I
/ O
操作的杂物箱。不能用本章中其他函数表示的
I / O
操作通常都能用
i o c t l
表示。终端
I / O

ioctl
的最大使用方面,主要用于设备的
I / O
控制。

#include
<unistd.h> /* SVR4 */

#include
<sys/ioctl.h> /* 4.3+BSD * /

int ioctl(int filedes
,
int request
, . . . ) ;

返回:若出错则为
- 1
,若成功则为其他值

I/O
处理的五种模型



阻塞
I/O
模型:若所调用的
I/O
函数没有完成相关的功能就会使进程挂起,直到相关数据到达才会返回。如:终端、网络设备的访问。



非阻塞模型:当请求的
I/O
操作不能完成时,则不让进程休眠,而且返回一个错误。如:
open

read

write
访问。



I/O
多路转接模型:如果请求的
I/O
操作阻塞,且他不是真正阻塞
I/O
,而且让其中的一个函数等待,在这期间,
I/O
还能进行其他操作。如:
select
函数。



信号驱动
I/O
模型:在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动
I/O




异步
I/O
模型:在这种模型下,当一个描述符已准备好,可以启动
I/O
时,进程会通知内核。由内核进行后续处理,这种用法现在较少

#include
<sys/types.h>/* fd_set data type */

#include
<sys/time.h> /* struct timeval */

#include
<unistd.h> /* function prototype

might be here */

int select (int numfds
,
fd_set *readfds
,

fd_set *writefds
, fd_set *exceptfds
,
struct timeval * timeout
)
;

返回:准备就绪的描述符数,若超时则为
0
,若出错则为
- 1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: