📅  最后修改于: 2023-12-03 15:28:44.980000             🧑  作者: Mango
本题是GATE-CS-2016(套装1)的第4道问题,考查了解Unix系统调用的特性与实现细节,需要注意一些常见的陷阱。
下面的程序段在Unix系统上运行。函数printBlocks()会按照相应的顺序打印每个块的字节数。请填写缺失的代码块,使得程序按照期望的方式运行。
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
void printBlocks(const char *fname) {
struct stat st;
if ( stat(fname, &st) == -1)
return;
printf("Blocks: %ld\n", st.st_blocks);
}
int main(int argc, char *argv[]) {
char *fname = argv[1];
int fd;
/* Fill in the missing code */
printBlocks(fname);
return 0;
}
例如,如果编译并运行程序,传入一个文件名为/tmp/myfile.txt
,则期望输出如下:
$ gcc -o myfile myfile.c && ./myfile /tmp/myfile.txt
Blocks: 16
注意,在Linux中,一个文件的长度被存储为byte数(字节数),而一个块的大小取决于文件系统。
本题实际上考查了Unix系统调用中的lseek
、read
、close
等的使用方式,以及文件描述符、进程间通信等底层概念。具体而言,我们需要先调用open
打开文件,得到一个文件描述符,然后再调用stat
函数读取文件信息(包括st_blocks信息),最后需要调用close
函数关闭文件。在其中很容易出现一些常见的陷阱,比如忘记检查文件打开是否成功、文件描述符的控制权转移、文件的权限检查等等。
由于限制篇幅,这里不再赘述这些具体实现细节。感兴趣的读者可以前往Unix编程手册等资源中查看更详细的内容。
下面是可能的一个参考代码(仅供参考,略有简化):
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
void printBlocks(const char *fname) {
struct stat st;
if ( stat(fname, &st) == -1)
return;
printf("Blocks: %ld\n", st.st_blocks);
}
int main(int argc, char *argv[]) {
char *fname = argv[1];
int fd;
// 打开文件
if ( (fd = open(fname, O_RDONLY)) == -1 ) {
perror("Error opening file");
return 1;
}
printBlocks(fname);
// 关闭文件
if ( close(fd) == -1 ) {
perror("Error closing file");
return 1;
}
return 0;
}
其中,open
函数的第二个参数确定了打开文件的模式(读、写、追加等),常用标志符包括O_RDONLY
(只读模式)、O_WRONLY
(只写模式)以及O_CREAT
(如果文件不存在则创建)等。调用close
函数时需要检查返回值是否为-1,因为在关闭文件时可能会出现一些错误,比如文件不是打开状态等。