写文件与错误处理
一、背景
上一篇总结探究了who的实现过程。学会了使用联机帮助来为自己披荆斩棘、解决问题。who命令从utmp结构中读出数据并且通过标准输出方式输出。而并未往文件中写数据。这一篇总结将会讨论之。另外将讨论linux系统调用的错误处理方式。
二、写文件
1.查找写文件的系统调用
写文件的系统调用当然可以直接从书中查找到是write。但运用联机帮助的知识也很容易的查找到。首先要联想到写文件相关联的一定是读文件系统调用read,read现在已经熟悉了。那么在SEE ALSO中就可以看到写文件为write。
接下来当然是用帮助文档查看下write的使用方法。
头文件与使用方法皆在其中。
2.编写cp命令
cp命令是复制粘贴命令,它会在你指定的位置创建一个新的文件并将你指定的旧文件的内容写入到新文件中。明白原理后就应该知道这里需要这几个系统调用:打开旧文件、创建新文件、读旧文件到缓冲区、写缓冲区的数据至新文件、将两个文件都关闭。这里除了创建新文件现在还不知道使用哪个系统调用外,其它的系统调用都已经使用过了。
不过这里用联机帮助我也没在SEE ALSO中找得到新建文件的系统调用。在书上查找到使用creat并使用联机帮助查询其头文件与使用方法。
在这里我发现它的使用方法与open的使用方法极为相似。而且SYNOPSIS(概览)都是一样的。只怪自己大意,其实在open中就应该想到creat是创建新的文件系统调用了。
cp命令的实现代码如下:
#include
#include
#include
#include
#define LEN 10000
#define MODE 0644
void error(char *,char *);
int main(int argc,char *argv[])
{
int in_fd,out_fd,number;
char buffer[LEN];
if(argc!=3)
{ fprintf(stderr,"usage like this: %s source destination.\n",argv[0]);
exit(1);
}
if((in_fd=open(argv[1],O_RDONLY))==-1)
error("Cannot open the sourcefile.\n",argv[1]);
if((out_fd=creat(argv[2],MODE))==-1)
error("Cannot open the destinationfile.\n",argv[2]);
while((number=read(in_fd,buffer,LEN))>0)
if(write(out_fd,buffer,number)!=number)
error("failed to write to the destination.\n",argv[2]);
if(number==-1)
error("failed to read from the sourcefile.\n",argv[1]);
if((close(in_fd)==-1) || (close(out_fd))==-1)
error("failed to close the file","");
return 0;
}
void error(char *a,char *b)
{
fprintf(stderr,"error:%s",a);
perror(b);
exit(1);
}
这个程序的实现其实相对于who会简单一点。主要是需要处理好错误处理。错误处理后面会分析到。
二、处理系统调用中的错误
1.错误的出现
系统调用中可能会出现许多种类型的错误,比如open:当打开一个文件你却没权限时会报错,如果已经打开很多文件内存不足也会报错,如果你打开的这个文件根本就不存在,当然也会报错。总之错误方式多多。而无论是open、creat还是read、write、close,报错都是会返回一个值:-1的。
2.确定错误种类
种类繁多的错误,都只是返回-1,可若要进行某种修正,那么编程者知道到底是何种错误就显得尤其重要了。确定错误种类的命令errno,查看其联机帮助可以看到各种错误代码的说明,多得数不胜数。我随便截了一部分。也就是说,当errno==(某个错误代码)时,就应该是某种错误类型,在标准输出就应该输出其对应的说明了。程序示例如下:
#include
extern int errno;
int sample()
{
int fd;
fd=open("file",O_RDONLY);
if(fd==-1)
{
printf("Cannot open file:");
if(errno==ENOENT)
printf("There is no such file.\n");
if(errno==EINTR)
printf("Interrupted while opening file.\n");
if(errno==EACCESS)
printf("You do not have permission to open file.\n");
...
这段程序是不完整的程序,就是为了说明每一种错误类型均对应某一种应标准输出的错误说明。
3.perror
这个命令是一种更为方便省心的错误处理方式。之前我的程序代码中就多次出现了。将前面的sample程序修改一下:
int sample()
{
int fd;
fd=open("file",O_RDONLY);
if(fd==-1)
{
perror("cannot open this file");
exit(1);
...
由此可以看出这种错误输出方式确实简单方便的多。所以非常常用。
这里看一个实例,刚才编写的cp命令来错误的使用:
我用自己编写的cp来复制123到3.c,可以看到其报错信息如前所述。
三、总结
写文件沿袭了上一次的总结,只是新学习了两个系统调用:creat、write。而处理调用中的错误就是学会使用perror命令。errno运作方式了解即可。