最近,在看《深入理解计算机系统》,在看到虚拟存储器这一章节时,遇到一个习题:
编写一个C程序mmapcopy.c, 使用mmap将一个任意大小的磁盘文件拷贝到stdout。输出文件的名字必须作为一个命令行参数来传递。
google了一下,下面附上代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 
 | #include <stdio.h>#include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/mman.h>
 int main (int argc, char *argv[])
 {
 struct stat sb;
 off_t len;
 char *p;
 int fd;
 if (argc < 2) {
 fprintf (stderr, "usage: %s <file>\n", argv[0]);
 return 1;
 }
 fd = open (argv[1], O_RDONLY);
 if (fd == -1) {
 perror ("open");
 return 1;
 }
 if (fstat (fd, &sb) == -1) {
 perror ("fstat");
 return 1;
 }
 if (!S_ISREG (sb.st_mode)) {
 fprintf (stderr, "%s is not a file\n", argv[1]);
 return 1;
 }
 p = mmap (0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
 if (p == MAP_FAILED) {
 perror ("mmap");
 return 1;
 }
 if (close (fd) == -1) {
 perror ("close");
 return 1;
 }
 for (len = 0; len < sb.st_size; len++)
 putchar (p[len]);
 if (munmap (p, sb.st_size) == -1) {
 perror ("munmap");
 return 1;
 }
 return 0;
 }
 
 | 
对于这个代码,下面附上我的收获:
- 以前写代码的时候很少考虑出错处理,在看到这段代码的时候,顿时收获良多
- fprintf stderr的用法很重要,同时要区别与stdout的关系(区别)
- 利用main函数进行命令行参数的传递,int main (int argc, char *argv[]),main函数 return 0 代表成功,return 非0 代表error
- perror()的用法:- 
- 函数- perror()用于抛出最近的一次系统错误信息,其原型如下:
 - void perror(char *string);
 - 说明:- perror()用来将上一个函数发生错误的原因输出到标准错误(stderr)。参数string所指的字符串会先打印出,后面再加上错误原因字符串,此错误原因依照全局变量errno的值来决定要输出的字符串。
 
 
- fstat( ) returns information about a given file
- off_t代表文件的偏移,与size_t的区别和联系可参考stackoverflow
参考资料:
- safaribooksonline