linux系统编程,常见系统函数[open/read/write/lseek/close]

linux系统编程、系统函数  

大多数U N I X文件I / O只需用到5个函数:o p e nr e a dw r i t elseek 以及c l o s e

系统函数介绍

函数open()

调用o p e n函数可以打开或创建一个文件。

===============================================================================
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char * p a t h n a m e,  int o f l a g,.../*,  mode_t m o d e * / ) ;
返回:若成功为文件描述符,若出错为- 1

===============================================================================

o p e n函数而言,仅当创建新文件时才使用第三个参数。

 

p a t h n a m e是要打开或创建的文件的名字。

o f l a g参数可用来说明此函数的多个选择项。

用下列一个或多个常数进行或运算构成o f l a g参数(这些常数定义在< f c n t l . h >头文件中)
O_RDONLY 只读打开。
O_WRONLY 只写打开。
O_RDWR 读、写打开。
很多实现将O _ R D O N LY定义为0O _ W R O N LY定义为1O _ R D W R定义为2,以与早期的系统兼容。
在这三个常数中应当只指定一个。下列常数则是可选择的:
O_APPEND 每次写时都加到文件的尾端。3 . 11节将详细说明此选择项。


O_CREAT 若此文件不存在则创建它。使用此选择项时,需同时说明第三个参数m o d e
用其说明该新文件的存取许可权位。 ( 4 . 5节将说明文件的许可权位,那时就能了解如何说明m o d e,以及如何用进程的u m a s k值修改它。 )


O_EXCL 如果同时指定了O _ C R E AT,而文件已经存在,则出错。这可测试一个文件是
否存在,如果不存在则创建此文件成为一个原子操作。 3 . 11节将较详细地说明原子操作。


O_TRUNC 如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0


O_NOCTTY 如果p a t h n a m e指的是终端设备,则不将此设备分配作为此进程的控制终端。9 . 6节将说明控制终端。


O_NONBLOCK 如果p a t h n a m e指的是一个F I F O、一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I / O操作设置非阻塞方式。1 2 . 2节将说明此工作方式。

函数creat()

===============================================================================

也可用c r e a t函数创建一个新文件。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char * p a t h n a m e, mode_tm o d e) ;
返回:若成功为只写打开的文件描述符,若出错为- 1
注意,此函数等效于:
o p e n (p a t h n a m e, O_WRONLY O _ C R E A TO_TRUNC, m o d e) ;

===============================================================================

注意:

在早期的U N I X版本中,o p e n的第二个参数只能是012。没有办法打开一
个尚未存在的文件,因此需要另一个系统调用 c r e a t以创建新文件。现在,o p e n
数提供了选择项O _ C R E ATO _ T R U N C,于是也就不再需要c r e a t函数了。

 

c r e a t的一个不足之处是它以只写方式打开所创建的文件。在提供 o p e n的新版本之前,如果要创建一个临时文件,并要先写该文件,然后又读该文件,则必须先调用c r e a tc l o s e,然后再调用o p e n。现在则可用下列方式调用o p e n
o p e n (p a t h n a m e, O_RDWR O _ C R E A TO_TRUNC, m o d e) ;

 

函数close()

===============================================================================

#include <unistd.h>
int close (int f i l e d e s)
返回:若成功为 0,若出错为- 1

===============================================================================

关闭一个文件时也释放该进程加在该文件上的所有记录锁。 当一个进程终止时,它所有的打开文件都由内核自动关闭。很多程序都使用这一功能而不显式地用c l o s e关闭打开的文件。


记录锁( record locking)的功能是:一个进程正在读或修改文件的某个部分时,可以阻止其他进程修改同一文件区。对于U N I X, “记录”这个定语也是误用,因为U N I X内核根本没有使用文件记录这种概念。一个更适合的术语可能是“区域锁”,因为它锁定的只是文件的一个区域(也可能是整个文件)。

函数lseek()

按系统默认,当打开一个文件时,除非指定O _ A P P E N D选择项,否则该位移量被设置为0。可以调用l s e e k显式地定位一个打开文件。


===============================================================================

#include <sys/types.h>
#include <unistd.h>
off_t lseek(int f i l e d e s, off_t o f f s e t, int w h e n c e) ;

返回:若成功为新的文件位移,若出错为- 1

===============================================================================


对参数offset 的解释与参数w h e n c e的值有关。
• 若w h e n c eS E E K _ S E T,则将该文件的位移量设置为距文件开始处offset 个字节。
• 若w h e n c eS E E K _ C U R,则将该文件的位移量设置为其当前值加offset, offset可为正或负。
• 若w h e n c eS E E K _ E N D,则将该文件的位移量设置为文件长度加offset, offset可为正或负。
l s e e k成功执行,则返回新的文件位移量,为此可以用下列方式确定一个打开文件的当前位移量:
off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);
这种方法也可用来确定所涉及的文件是否可以设置位移量。如果文件描述符引用的是一个管道或F I F O,则l s e e k返回-1,并将e r r n o设置为E P I P E


三个符号常数 S E E K _ S E TS E E K _ C U RS E E K _ E N D是由系统V引进的。在系统V之前,w h e n c e被指定为0 (绝对位移量)1 ( 相对于当前位置的位移量)2 (相对文件尾端的位移量)。很多软件仍直接使用这些数字进行编码。
l s e e k中的字符l表示长整型。在引入o ff _ t数据类型之前,o f f s e t参数和返回值是长整型的。l s e e k是由V 7引进的,当时C语言中增加了长整型。(V 6中,用函数s e e kt e l l提供类似功能。 )

 

实例:

下面截图是使用lseek() 函数拓展一个文件

 

下面截图是使用lseek()函数 计算一个文件的大小:

 

代码如下:

/*************************************************************************

  > File Name: lseek.c

  > Created Time: 20160730日 星期六115404

 ************************************************************************/

#include<stdio.h>

#include<stdlib.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<unistd.h>

#include<errno.h>

int main(void)

{

int fd = open("abc", O_RDWR);

 

if(fd < 0){

perror("open abc");

exit(-1);

}

//拓展一个文件,必须有一次写操作

lseek(fd, 0x1000, SEEK_SET);   0x1000 = 16^3 = 2^4^3 = 2^12 = 4096

write(fd, "a", 1);

 

close(fd);

//计算打开文件的大小

fd = open("hello", O_RDWR);

 

if(fd < 0){

perror("open hello");

exit(-1);

}

printf("hello size = %d\n", lseek(fd, 0, SEEK_END));

close(fd);

return 0;

}

 

函数read()

===============================================================================

r e a d函数从打开文件中读数据。
#include <unistd.h>
ssize_t read(int f i l e d e s, void * b u f f, size_tn b y t e s) ;
返回:读到的字节数,若已到文件尾为 0,若出错为- 1

===============================================================================


r e a d成功,则返回读到的字节数。如已到达文件的尾端,则返回0
有多种情况可使实际读到的字节数少于要求读字节数:
• 读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之
前还有3 0个字节,而要求读1 0 0个字节,则r e a d返回3 0,下一次再调用r e a d时,它将返回0 (文件尾端)
• 当从终端设备读时,通常一次最多读一行 (11章将介绍如何改变这一点)
• 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。
• 某些面向记录的设备,例如磁带,一次最多返回一个记录。


读操作从文件的当前位移量处开始,在成功返回之前,该位移量增加实际读得的字节数。
P O S I X . 1在几个方面对此函数的原型作了更改。其经典定义是:
int read(intf i l e d e s, char * b u f f, unsignedn b y t e s) ;
首先,为了与ANSI C一致,其第二个参数由char *改为void *。在ANSI C中,类型void *用于表示类属指针。其次,其返回值必须是一个带符号整数(s s i z e _ t),以返回正字节数、0(表示文件尾端)或-1(出错)。最后,第三个参数在历史上是一个不带符号整数,以允许一个1 6位的实现可以一次读或写至6 5 5 3 4个字节。在1990 POSIX.1标准中,引进了新的基本系统数据类型ssize_t以提供带符号的返回值, s i z e _ t则被用于第三个参数(见表2 - 7中的S S I Z E _ M A X常数)。

函数write()

===============================================================================

w r i t e函数向打开文件写数据。
#include <unistd.h>
ssize_t write(int  f i l e d e s,  const void * b u f f,  size_t n b y t e s) ;
返回:若成功为已写的字节数,若出错为- 1

===============================================================================


其返回值通常与参数 n b y t e s的值不同,否则表示出错。w r i t e出错的一个常见原因是:磁盘已写满,或者超过了对一个给定进程的文件长度限制(7 . 11节及习题1 0 . 11 )
对于普通文件,写操作从文件的当前位移量处开始。如果在打开该文件时,指定了
O _ A P P E N D选择项,则在每次写操作之前,将文件位移量设置在文件的当前结尾处。在一次成功写之后,该文件位移量增加实际写的字节数。

 

函数readwrite实现cp 命令

/*************************************************************************

> File Name: mycp.c

> Author: xuxing

> Mail: xuxing@163.com

> Created Time: 20160729日 星期五134900

 ************************************************************************/

 

#include<stdio.h>

#include<stdlib.h>

#include<sys/stat.h>

#include<sys/types.h>

#include<fcntl.h>

#include<unistd.h>

 

#define SIZE   8192

 

int main(int argc, char *argv[])

{

char buf[SIZE];

int fd_src, fd_dest, len;

 

if(argc < 3 ) {

        printf("./mycp src dest\n");

            exit(1);

}

 

fd_src = open(argv[1], O_RDONLY);

fd_dest = open(argv[2],O_CREAT | O_WRONLY | O_TRUNC, 0644 );

 

/*

 *success return read the number of bytes

 *read the file last

 *failed return -1

 */

while((len = read(fd_src, buf, sizeof(buf))) > 0)

write(fd_dest, buf, len);

 

close(fd_src);

close(fd_dest);

 

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值