UNIX环境高级编程读书笔记(一)—文件IO (2)
来源:互联网 发布:天赋异禀美剧 知乎 编辑:程序博客网 时间:2024/05/21 07:01
5.
名称: | write |
目标: | 将内存中的数据写入文件。 |
头文件: | #include < unistd.h> |
函数原形: | size_t write(int fd, const void *buf, size_t count) |
参数: | fd 文件描述符 |
buf 内存数据 | |
count 要写的字节数 | |
返回值: | -1 遇到错误 |
| Num written 成功写入,返回写入的字节数目。 |
在实际的写入过程中,可能会出现写入的字节数少于所要求的。这可能有两个原因,第一是有的系统对文件的最大尺寸有限制,第二是磁盘空间接近满了。在上述两种情况下内核都会尽力把数据往文件中写,并将实际写入的字节数返回,所以调用write后都必须检查返回值是否与要写入的相同,如果不同就要采取相应的措施。
学完上面几个系统调用,我们就可以自己编写的cp命令了。它的基本思路是从原文件读取数据写入缓冲,再将缓冲的数据写入目标文件。
/*1_3.c*/ #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #define BUFFERSIZE 4096 #define COPYMODE 0644 void oops(char *s1,char *s2); main(int argc,char *argv[]) { int in_fd,out_fd,n_chars; char buf[BUFFERSIZE]; if(argc!=3) { fprintf(stderr,”usage:%s source destination/n”,*argv); exit(1); } if((in_fd=open(argv[1],O_RDONLY))==-1) oops(“Cannot open”,argv[1]); if((out_fd=creat(argv[2], COPYMODE))==-1) oops(“Cannot creat”,argv[2]); while((n_chars=read(in_fd,buf,BUFFERSIZE))>0) { if(write(out_fd,buf,n_chars)!=n_chars) oops(“Write error to”,argv[2]); } if(n_chars==-1) opps(“Read error form”,argv[1]); if(close(in_fd)==-1||close(out_fd)==-1) oops(“Error clising files”); } void oops(char *s1,char *s2) { fprintf(stderr,”Error:%s”,s1); perror(s2); exit(1); } |
三、文件描述符操作函数
6.
名称:: | lseek |
目标: | 使指针指向文件中的指定位置。 |
头文件: | #include <sys/types.h> #include <unistd.h> |
函数原形: | off_t lseek(int fildes,off_t offset,int whence) |
参数: | fildes 文件描述符 offset 移动的距离 wence SEEK_SET=>文件的开始 SEEK_CUR=>当前位子 SEEK_END=>文件结束 |
返回值: | -1 遇到错误 Ildpos 指针变化前的位子 |
lseek改变文件描述符所关联的指针的位置,新的位置由offset和wence来指定,wence是基准位置,基准位子可以是文件的开始(0)、当前位子(1)或文件的结束(2)。 offset是从基准位子开始的偏移量。若wence为SEEK_SET,该文件的偏移设置为距文件开始处offset个字节数。若wence是SEEK_CUR,该文件的偏移设置为其当前值加offset, offset可为正或负。若wence是SEEK_END,该文件的偏移设置为文件长度加offset, offset可为正或负。
lseek(fd,0,SEEK_END);
文件位偏移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中没有写过的字节都被读为0。
下面是一个例子:
/*1_4.c*/ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> char buf1[]=”abcdefg”; char buf2[]=”ABCDEFG”; int main(void) { int fd; if((fd=creat(“file.hole”,0644))==-1) printf(“creat error”); if(write(fd,buf1,7)!=7) printf (“buf1 write error”); if(lseek(fd,40,SEEK_SET)==-1) printf (“lseek error”); if(write(fd,buf2,7)!=7) printf (“buf2 write error”); exit(0); } |
7.
名称:: | dup/dup2 |
目标: | 复制一个现存的文件描述符. |
头文件: | #include <unistd.h> |
函数原形: | int dup(int oldfd) int dup2(int oldfd,int newfd) |
参数: | oldfd 原有文件描述符 newfd 新的文件描述符 |
返回值: | -1 遇到错误 int 新文件描述符 |
系统调用dup是用来复制一个文件描述符,也就是将进程u区的文件描述符表中的一项复制一份,使得这两项同时指向系统稳健表的同一表项。
系统调用dup复制由参数oldfd指定的文件描述到进程文件描述符表的第一个空表项处。而系统调用dup2复制由参数oldfd指定的文件描述到参数newfd指定的文件描述符表项处。老的文件描述符和新复制的文件描述符可以互换使用。它们共享锁、文件指针和文件状态。例如,对其中一个文件描述符使用系统调用lseek修改文件指针的位置,对另一文件描述符来说文件指针也改变了,其实我们了解了内核的工作原理,这一点很容易理解。因为我们知道,文件指针是放在系统文件表中的。但这两个文件描述符具有不同的close-on-exec标志,因为该标志是存放在文件描述符表中的。
该调用成功时,返回值为新的描述符;错误时,返回-1,并设置相应的错误代码errno:
- EBADF:参数oldfd不是一个已经打开的文件描述符;或者参数newfd超出允许的文件描述符的取值范围。
- EMFILE:进程打开的文件描述符数量已经到达最大值,但仍然企图打开新的文件描述符。
下面我们来看一个简单的例子。在这个例子中,我们将标准输出(文件描述符为1)关闭,并将一个打开了普通文件“output”的文件描述符复制到标准输出上,因为刚关闭了文件描述符1,所以,文件描述符表的第一个空表项是1。所以,程序以后的printf等向标准输出写的内容都写到了文件中。
利用这个功能我们可以把输出/输入重定向到文件中。下面是一个例子。
/*1_5.c*/ #include <stdio.h> #include <unistd.h> #include <systypes.h> #include <sys/stat.h> #include <string.h> #include <errno.h> #include <fcntl.h> main(int argc,char *argv[])
close(fd); /* 即时关闭不用的文件描述符是一个好习惯 */ 该程序执行过程的屏幕拷贝: [wap@wapgw /tmp]$ gcc -o 1_5 1_5.c |
dup2的功能和dup基本相同,只不过是dup2复制oldfd到newfd上。下面是用dup2实现同样的例子。
/*1_6.c*/ #include <stdio.h> #include <unistd.h> #include <systypes.h> #include <sys/stat.h> #include <string.h> #include <errno.h> #include <fcntl.h> main(int argc,char *argv[]) { int fd; if((fd=open(argv[1],O_WRONLY|O_CREAT,0644))==-1) perror(“error”); close(1); if(dup2(fd,1)==-1) perror(“error”); close(fd); printf(“This line will write to file /n”); close(fd); } |
利用这两个函数我们可以实现管道的功能,有关管道的内容将在后面介绍。
8.
名称:: | fcntl | |
目标: | 改变已经打开文件的性质。 | |
头文件: | #include <unistd.h> #include <sys/types.h> #include <fcntl.h> | |
函数原形: | int fcntl(int fd,int cmd); int fcntl(int fd,int cmd,long arg); int fcntl(int fd,int cmd,struct flock *lock); | |
参数: | fd 文件描述符 cmd 功能描述位 | |
返回值: | -1 遇到错误 V-node |
fcntl函数有5种功能:
1 复制一个现存的文件描述符(cmd=F_DUPFD)
2 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD)
3 获得/设置文件状态标志(cmd=F_GETFL或F_SETFL)
4 获得/设置异步I/O所有权(cmd=F_GETOWN 或F_SETOWN)
5 获得/设置记录锁(cmd=F_GRTLK,F_SETLK或F_SETLKW)
fcntl的功能之一是重复文件描述字。
fcntl (FileDescriptor, F_DUPFD, 0)等价于Dup(FileDescriptor)
close (New); fcntl(Old, F_DUPFD, New)等价于dup2 (Old,New)
fcntl的功能之二获得/设置文件描述符标记。
获得文件描述标记fcntl (FileDescriptor, F_GETFD)
设置文件描述标记fcntl(FileDescriptor, F_SETFD, flags)
fcntl的功能之三获得/设置文件状态标签,文件状态标签分为3类它们是文件访问方式、打开时标志和I/O操作方式。
本文转自http://blog.chinaunix.net/u1/59291/showart.php?id=538539
- 文件io(一)--unix环境高级编程读书笔记
- UNIX环境高级编程读书笔记(一)—文件IO (2)
- UNIX环境高级编程读书笔记(一)—文件IO (2)
- UNIX环境高级编程读书笔记(一)—文件IO (2)
- 《UNIX环境高级编程》读书笔记之文件IO(2)
- 高级IO(一)--UNIX环境高级编程读书笔记
- UNIX环境高级编程读书笔记(一)—文件IO (1)
- UNIX环境高级编程读书笔记(一)—文件IO (1)
- UNIX环境高级编程读书笔记(一)—文件IO (1)
- 《UNIX环境高级编程》读书笔记之文件IO(1)
- UNIX环境高级编程-读书笔记-文件操作(一)
- Unix环境高级编程读书笔记(一)
- UNIX环境高级编程读书笔记(十二)—高级IO (2)
- UNIX环境高级编程读书笔记(十二)—高级IO (2)
- UNIX环境高级编程读书笔记(十二)—高级IO (2)
- UNIX环境高级编程读书笔记(十一)—终端IO (2)
- UNIX环境高级编程读书笔记(十一)—终端IO (2)
- UNIX环境高级编程读书笔记(十一)—终端IO (2)
- 深圳万人购房团欲腰斩房价
- ASP.NET 中处理页面“回退”的方法
- 肖申克的救赎 经典台词
- 如何用C#在Asp.net中实现打开新网页而不关闭当前页
- 另一种不同风格的图片播放器(图片画廊,photogallery),附源代码
- UNIX环境高级编程读书笔记(一)—文件IO (2)
- php+smarty生成静态页面详解
- session的基本用法
- C# 中String 和 string 的区别
- 五横五纵快速交通系统提速大连经济
- 项目经理怎样处理技术见解不同导致的人员冲突?
- 刘翔"0.02战靴"亮相耐克798 全球限量生产10双
- UNIX环境高级编程读书笔记(二)—目录和文件(1)
- 在linux下面安装gcc