1.chmod 函数和fchmod函数
chmod和fchmod函数包含在头文件<sys/types.h>和<sys/stat,h>中 原型;int chmod(const char *path,mode_t mode); int fchmod(int fildes,mode_t mode); 区别:chmod函数第一个参数是文件名,fchmod以文件描述符作为第一个参数;
参数:第一个参数path是要设置权限的文件名,第二个参数mode
参数mode的数值一般有以下几种组合: S_IRUSR 00400 文件所有者具有可读权限; S_IWUSR 00200 文件所有者具有可写入的权限; S_IXUSR 00100 文件所有者具有可执行的权限; S_IRGRP 00040 用户组具有可读取的权限; S_IWGRP 00020 用户组具有可写入的权限; S_IXGRP 00010 用户组具有可执行的权限; S_IROTH 00004 其它用户具有可读取的权限 S_IWOTH 00002 其它用户具有可写入的权限 S_IXOTH 00001 其它用户具有可执行的权限 S_ISUID 04000 文件的(set user-id on execution)位; S_ISGID 02000 文件的(set group-id on excution)位; S_ISVTX 01000 文件的sticky; sticky位是什么鬼,上网查了一下:sticky也就是粘滞位,普通文件的粘滞位会被内核忽略,如果目录设置有粘滞位,如果用户对目录有写入权限,则可以删除其中的文件,即使不是目录的所有者,对文件并没有写的权限.但是,当设设有粘滞位时,就只能是root,和ower 才有删除里面文件的权限;
2.open()函数creat()函数和close()函数
open函数和creat函数都包含在头文件<sys/types.h>.<sys/stat.h>.<fcntl.h> 原型:int open(const char *pathname,int flag); int open(const char *pathname,int flag,mode_t mode); 其中第一个参数pathname是要打开的或创建的含路径的文件名,第二个参数flags表示flags表示打开文件的方式: 1.O_RDONLY:以只读的方式打开; 2.O_WRONLY:以只写方式打开; 3 .O_RDWR:以可读可写的方式打开; 这三种打开方式是互斥的,不能同时以两种或三种打开,但是他们可以分别与下列标志结合: 1.O_CREAT:若文件不存在则自动建立该文件,只有在文件不存在建立文件的时候才可以用到第三个参数mode; 2.O_EXCL:如果O_CREAT也被设置,此指令会去检查文件是否存在,文件不存在则创建文件,文件存在则导致打开文件失败; 3.O_TRUNC:若文件存在,并且可以以可写方式打开时,此标志则将文件长度清零0,及原文中保存的数据将丢失;文件的属性不变; 4.O_APPEND:所有写入的数据都会以追加的方式加入到文件后面; 5.O_SYNC:以同步的方式打开,任何队文件的修改都会阻塞直到物理磁盘上的数据同步后才返回; 6.O_NOFOLLOW:如果参数pathname所指的文件为一符号连接,则会打开失败; 7.O_DIRECTORY:如果参数所指的文件并非为一目录,则会令文件打开失败; 成功调用open()会返回一个文件描述符,错误返回-1; 参数mode和chmod函数相同;详情请戳:chmod函数和fchmod函数,umask命令; 新文件的实际存取权限是(mode&~umask)运算后的结果; umask是什么鬼,它是权限掩码,什么是权限掩码呢,大家都知道,当你创建一个文件一般不用chmod命令去设置文件的权限,那么是不是,创建一个文件的权限就是666(对于文件来说,系统不允许你在创建的时候就为其赋予执行权限,所以这里我说666, 目录则可以取到777)呢,来看例子:
yang@liu:~$ umask 0022 yang@liu:~$ touch 22.c yang@liu:~$ ls -l 22.c -rw-r--r-- 1 yang yang 0 7月 20 11:42 22.c
umask的一般默认值是0022;也就是说权限掩码的左用就是限制其他人对文件的操作权限,在你创建文件时完成,不用自己去手动设置权限;现在,问题来了,这是怎样运算的呢; mode和umask是怎样运算的呢,有很多办法,用最简单的来说: 计算u m a s k值的方法:我们只要记住u m a s k是从权限中“拿走”相应的位即可。 如果umask为023,则对于文件所有者,不拿去任何权限,而新建的文件默认没有执行权限,故对文件所有者的权限位rw-(6);对组所有者,拿去写权限,原本没有执行权限,故为r--(4);对其他用户,拿去写和执行权限,原本没有执行权限,故为r--(4); 如果umask为023,因为没有新建目录没有执行权限的限制。则对于目录所有者,不拿去任何权限,故对目录所有者的权限为rwx(7);对组所有者,拿去写权限,故为r-x(5);对其他用户,拿去写和执行权限,故为r--(4); Creat()函数 原型:int creat(const char *pathname,mode_t mode); 其中第一个参数pathname是要打开或创建的文件名,如果pathname指向的文件不存在,则创建一个新文件,如果pathname指向的文件存在,则原文件,被新文件覆盖,第二个参数mode与open函数相同;creat()相当于这样使用open(); open(const char *pathname,(O_CREAT | O_WRONLY | O_TRUNC)); 成功调用open()会返回一个文件描述符,错误返回-1; 有没有发现什么呢,creat()和open(const char *pathname,(O_CREAT | O_WRONLY | O_TRUNC));打开文件是等价的,仔细一点你会发现open函数是以只写方式打开的,而这样用open()打开的文件和用creat()打开的文件等价,这能说明什么呢,注意 这说明creat() 只能以只写方式打开,也就是说,用creat()函数打开的文件,只能往文件里写数据,而不能从文件里读数据,如果用creat()函数打开文件,调用read()读取数据,就会出现error;来看个例子:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <error.h> #include <string.h> /*自定义的错误处理函数*/ void my_err(const char *err_string,int line) { fprintf(stderr,"line:%d ",line); perror(err_string); exit(1); } /*自定义的读数据函数*/ int my_read(int fd) { int len; int ret; int i; char read_buf[64]; /*获取文件长度并保持文件读写指针在文件开始处*/ /*if (lseek(fd,0,SEEK_END)==-1) { my_err("lseek",__LINE__); }*/ if((len=lseek(fd,0,SEEK_CUR))==-1) { my_err("lseek",__LINE__); } if((lseek(fd,0,SEEK_SET))==-1) { my_err("lseek",__LINE__); } printf("len:%d\n",len); /*读数据*/ if((ret = read(fd,read_buf,len))<0) { my_err("read",__LINE__); } /*打印数据*/ for(i=0;i<len;i++) { printf("%c",read_buf[i]); } printf("\n"); return ret; } int main() { int fd; char write_buf[32]="Hello,World!"; /*在当前目录下创建文件example_63.c*/ //if((fd = creat("example_63.c",S_IRWXU))==-1) {去掉注释, if((fd = open("example_63.c",O_RDWR | O_CREAT | 加注释O_TRUNC,S_IRWXU))==-1) { my_err("open",__LINE__); } else { printf("create file success\n"); } /*写数据*/ if(write(fd,write_buf,strlen(write_buf)) != strlen(write_buf)) { my_err("write",__LINE__); } my_read(fd); /*演示文件的间隔*/ printf("/*---------------------------------*/\n"); if(lseek(fd,10,SEEK_END)==-1) { my_err("lseek",__LINE__); } if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf)) { my_err("write",__LINE__); } my_read(fd); close(fd); return 0; }
第一次用open()打开文件运行结果:
yang@liu:~/Linux C$ ./a.out create file success len:12 Hello,World! /*---------------------------------*/ len:34 Hello,World!Hello,World!
第二次:按照代码的注释把"去掉注释的那一行注释去掉","加注释的那一行注释注释掉"也就是第二次以creat()方式打开,运行结果:
yang@liu:~/Linux C$ ./a.out
create file success
len:12
line:40 read: Bad file descriptor
可以发现,在第40行读数据的时候产生了错误; close()函数 close()函数包含在头文件<unistd.h> 原型:int close(int fd); close()函数只有一个参数,此参数表示需要关闭的文件的文件描述符,该文件描述符是由open()或creat得到.close调用成功,返回0,发生错误时-1;