这是一道描述很简短的练习题,就是让读者用书中之前介绍的mmap函数,写一个程序,将任意一个通过命令行指定的文件进行内存映射,然后输出这个文件的内容到stdout。这个题目最主干的知识,即mmap函数怎么使用,摆弄两下也就差不多了,但这道题还是卡到我去翻答案…( _ _)ノ,翻了答案才知道原来我是差额外没掌握的概念,所以这个程序没成功写出来。

先说自己对这道题的思考过程:这道题想让你命令行传递文件名,那么main函数的argc、argv肯定得有,然后向mmap传参是这样想的:我们让系统给我们做主该分配哪块空间就好,所以第一个参数就是NULL;第二个参数是映射的区块大小。我们想输出整个文件的内容,不需要额外分配空间,所以这个参数肯定和文件大小有关,但编程序的时候光靠自己没想到该怎么表达这个思路;第三个参数,因为我们需要把文件内容输出即可,所以传PROT_READ即可;第四个参数,我们是映射到一个普通的文件,不是共享库,所以传MAP_PRIVATE即可;第五个参数是文件描述符(现在知道不代表当时知道啊( ̄_ ̄|||)),当时看到“文件描述符”,没怎么想就把argv[1]传进去了,丢人……第六个参数是offset,这里输出全部文件内容,自然传入0。然后mmap返回一个指针,想到用一个char*指针接受这个返回值,然后printf(“%s”)接上,输出。之后又从网上查了一下,用stat函数,通过文件路径获得文件的元信息,把文件大小找出来,传进去mmap函数的区块大小参数。看起来挺不错,不过一运行就是segment fault。用断点调试去看,发现mmap返回的内存地址永远是0xffff……是一个无效值就对了。几次下来,决定去翻答案,发现是下面这些点不清楚:

文件描述符:首先这是一个int值,不是什么char*指针……引用stackOverflow上的一个回答:

In simple words, when you open a file, the operating system creates an entry to represent that file and store the information about that opened file. So if there are 100 files opened in your OS then there will be 100 entries in OS (somewhere in kernel). These entries are represented by integers like (…100, 101, 102….). This entry number is the file descriptor. So it is just an integer number that uniquely represents an opened file in operating system. If your process opens 10 files then your Process table will have 10 entries for file descriptors.


0, 1, 2 are standard FD‘s that corresponds to STDIN_FILENO, STDOUT_FILENO and STDERR_FILENO (defined in unistd.h) opened by default on behalf of shell when the program starts.
FD’s are allocated in the sequential order, meaning the lowest possible unallocated integer value.

https://stackoverflow.com/questions/5256599/what-are-file-descriptors-explained-in-simple-terms

然后这个值,是调用open函数,通过接受它的返回值去获取的。自然引出来open函数的介绍:

open函数:三个参数,第三个参数可选。分别为char*表示的文件路径名、flag和mode。mode只有在flag是O_CREAT时才需要考虑,这里用不上。flag挺像C里fopen里要传入的那些特定字符串,表示打开文件的方式。

write函数:答案里的代码使用了write函数来输出。printf函数并不是信号安全的函数,而write却是的,所以也记一下它的用法:三个参数,第一个是要写入的文件描述符;第二个是要写入的数据内容,用一个void*指针表示;第三个是要写入的数据大小。

stat、fstat函数的区别:两者都是传一个能指定特定文件的参数,加一个struct stat结构体的指针,得到一个含有特定文件元信息的结构体。不同在stat函数使用char*表示的路径来指示文件,而fstat需要传文件描述符。