小感慨
愉快的暑假留校学习开始啦,感慨一下,高考完了之后再次这样早起学习,一天过得格外快的日子好久没遇到了呢。。。
前述
暑假主要是学习LinuxC 还有系统的基本操作,今天主要看了文件操作,针对的都是一些系统调用函数。一天的学习快要结束了,趁着没忘赶紧总结一下吧。
首先说一下什么是系统调用,首先要纠正一个之前的错误观念,在做课设的时候有很多人都使用了system(“clear”)或者system(“cls”)
但是这并不是系统调用。
简单地说,system函数只是将传入的字符串交给shell去执行。而系统调用指的是操作系统提供给用户的一组接口,是用户程序和内核进行交互的一组接口,我自己对于底层,内核这些也不是很懂,希望在之后的学习中加深了解。
正文
1.文件权限控制
linux下一切皆文件,对于文件权限的控制自然是一大重点。可以通过chmod/fchmod函数对文件的访问权限进行修改,这这两者的区别在于chmod以文件名作为第一个参数,fchmod则是文件描述符,文件描述符我们后面再谈。
函数原型如下
int chmod(const char *path, mode_t mode);
int fchmod(int fildes, mode_t mode);
//成功返回0,否则返回-1
我认为首先一个重点是从这个函数我才分清 系统调用的函数和我们在shell下输入的命令并不相同,命令不等于系统调用函数 。
其次 mode_t 是unsigned int 类型的,不过按八进制进行解释,也就是说我们输入的777 要转换为八进制的511才能被函数正确的“理解”。
2.文件的创建,读写,关闭。
文件的创建可以通过open/creat函数来实现。函数原型如下
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
//成功返回文件描述符 失败返回-1
为什么open有两种形式呢?我认为是变参函数,此处先略过
open函数的用法和fopen非常像,为什么呢?
pathname是含路径的文件名不多说,flags表示打开文件的方式,分别是只读,只写,和可读可写,3种打开方式是互斥的。但是可以与一些标志进行或运算从而实现很多其他的方式。当或上O_CREAT标志时,表示若文件不存在则创建,此时需要第三个参数来设置新文件的权限,这里同chmod的参数。通过这些标志,creat函数可以看成时open函数的一种使用方式。
文件的关闭通过close函数,函数原型如下
int close(int fd);
//成功返回0,错误返回-1
close函数调用成功并不能保证全部数据写回磁盘。
3.文件读写
文件读写函数write/read,文件读写指针移动函数lseek。感觉还是lseek函数更有意思些。lseek允许文件指针的值设置到文件结束符之后,但这样做并不改变文件的大小(我感觉是由于linux的ext2/3/4文件系统将数据存放在data block,即使在文件结束符eof后面写入一些数据,如果当前的data block并未被写满所以显示的文件大小还是之前的data block 大小),如果使用write对eof之后的位置写入了数据,则在eof处和数据之间会存在一个间隔,用read读取的到的数据为0.
int main(void)
{
int fd;
char buf[4096];
char buf2[] = "l";
int i;
for(i = 0; i < 4096; i++)
buf[i] = 'a';
if((fd = open("./test/test.c",O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) == -1)
{
perror("open");
exit(1);
}
else{
printf("success\n");
write(fd, buf, 4096);
//第一次将下面两行注释掉,将一个4096字符串写入文件,恰好占一个blcok
//lseek(fd, 4096, SEEK_END);
//再次打开时将文件指针移动一个block大小,然后写入1字节
//write(fd, buf2,1);
close(fd);
return 0;
}
}
结果如下
由ls 可以看到 lseek移动的4096字节确实占了文件的空间,但并没有占用blcok,下图就可以看出
这种移动超出eof所形成的叫做文件空洞,这样的文件叫做稀疏文件。
文件系统存储稀疏文件时,inode索引节点中,只给出实际占用磁盘空间的Block 号,
数据全零且不占用磁盘空间的文件Block并没有物理磁盘Block号。
小结
学习这些函数的时候不禁想起了之前学的fopen fwrite fread fseek fclose,这些我们之前用的是C标准库的函数,我认为它们是由系统调用封装成的(所以在用法上十分相似),具有良好的移植性,可以跨平台使用,但系统调用函数是由操作系统提供的,不同的操作系统自然不同。
额外的心得
书上的例子几乎每个函数都记录了错误代码,方便查询错误信息,感觉有点麻烦不知道以后写的时候用不用加上,不过可能调试的时候比较方便吧。还有系统调用函数有的函数名和宏名(好多宏)都看不出什么意思,感觉需要好好学习英语了。。。