目录
一、linux系统文件和文件系统
1.1文件类型
1.2 system函数
1.3linux文件权限
1.4 设置系统文件、目录初始默认权限
1.5文件其他属性
/bin:
bin是Binary的缩写, 这个目录存放着最经常使用的命令。包括用户管理员命令,如:cat,chmod,cp,date,ls/boot:
这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。/dev :
dev是Device(设备)的缩写, 该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。/etc:
这个目录用来存放所有的系统管理所需要的配置文件和子目录。/home:
用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。/lib:
这个目录里存放着系统最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。如:c/c++等库文件 其他大部分文件存放在/usr/lib下/lost+found:
这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。/media:
linux系统会自动识别一些设备,例如U盘、光驱等等,当识别后,linux会把识别的设备挂载到这个目录下。双系统windows下的磁盘和插入的u盘都会在'media/用户名/' 目录下/mnt:
系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在/mnt/上,然后进入该目录就可以查看光驱里的内容了。/opt:
这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。应用商店里的好多软件包括deepinwine都在这里。(通过deepinwine安装的windows软件也在下面)/proc:
这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。
这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器:echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
/root:
该目录为系统管理员,也称作超级权限者的用户主目录。/sbin:
s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序。/selinux:
这个目录是Redhat/CentOS所特有的目录,Selinux是一个安全机制,类似于windows的防火墙,但是这套机制比较复杂,这个目录就是存放selinux相关的文件的。/srv:
该目录存放一些服务启动之后需要提取的数据。/sys:
这是linux2.6内核的一个很大的变化。该目录下安装了2.6内核中新出现的一个文件系统 sysfs 。
sysfs文件系统集成了下面3种文件系统的信息:针对进程信息的proc文件系统、针对设备的devfs文件系统以及针对伪终端的devpts文件系统。
该文件系统是内核设备树的一个直观反映。
当一个内核对象被创建的时候,对应的文件和目录也在内核对象子系统中被创建。
/tmp:
这个目录是用来存放一些临时文件的。/usr:
这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似于windows下的program files目录。/usr/bin:
系统用户使用的应用程序。/usr/sbin:
超级用户使用的比较高级的管理程序和系统守护程序。/usr/src:
内核源代码默认的放置目录。/var:
这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。/run:
是一个临时文件系统,存储系统启动以来的信息。当系统重启时,这个目录下的文件应该被删掉或清除。如果你的系统上有 /var/run 目录,应该让它指向 run。
在 Linux 系统中,有几个目录是比较重要的,平时需要注意不要误删除或者随意更改内部文件。
/etc: 上边也提到了,这个是系统中的配置文件,如果你更改了该目录下的某个文件可能会导致系统不能启动。
/bin, /sbin, /usr/bin, /usr/sbin: 这是系统预设的执行文件的放置目录,比如 ls 就是在/bin/ls 目录下的。
值得提出的是,/bin, /usr/bin 是给系统用户使用的指令(除root外的通用户),而/sbin, /usr/sbin 则是给root使用的指令。
/var: 这是一个非常重要的目录,系统上跑了很多程序,那么每个程序都会有相应的日志产生,而这些日志就被记录到这个目录下,具体在/var/log 目录下,另外mail的预设放置也是在这里。
普通文件(-)
目录文件(d)
符号链接文件(l)
字符设备文件(c)
块设备文件(b)
管道文件(p)
socket文件(s)
头文件:#include
函数功能:在进程中开始另一个进程
函数原型:int system(const char* string)
函数传入值:系统变量 shell命令
函数返回值:执行成功返回执行shell命令后的返回值;调用/bin/sh失败返回127;
其他原因失败则返回-1,;参数string为空(null),则返回非0值
备注:system()调用fork()产生子进程,子进程调用/bin/sh -c string来执行参数
string字符串所代表的命令,此命令执行完毕后随即返回原调用的进程。如果调用
成功,返回shell命令后的返回值可能也是127(该shell命令就返回数字结果127),
因此,最好能检查error来确定执行情况。
eg1:列出当前目录和系统目录'/dev/sda1' '/dev/lp0'下的信息
#include
#include int main(){ int newret; printf("列出当前目录下的文件信息:\n"); newret=system("ls -l"); printf("列出'/dev/sda1'下的文件信息:\n"); newret=system("ls /dev/sda1 -l"); printf("列出'/dev/lp0'下的文件信息:\n"); newret=system("ls /dev/lp0 -l"); return 0; } 运行结果:
eg2:编写一个c程序,用system函数调用一个shell函数,完成某文件中某一个字符的查找
/*完成某文件中某一字符串的查找*/ #include
#include #include int main(){ char a[100],b[100],cmd[100]; printf("请输入文件名:\n"); scanf("%s",a); printf("请输入字串:\n"); scanf("%s",b); strcpy(cmd,"./substr "); strcat(cmd,a); strcat(cmd," "); strcat(cmd,b); printf("执行命令:%s\n",cmd); system(cmd); return 0; } 运行结果:
eg3:编写c程序,用system函数调用另一个c程序
#include
#include int main(){ system("./5-1-1"); return 0; } 运行结果:同eg2 就是调用eg2的c程序
四种权限:可读r,可写w,可执行x,无权限-
头文件:#include
#include
函数功能:改变文件权限 (注意这是c语言函数 不是shell命令)
函数原型:int chmod(const char* path,mode_t mode)
函数传入值:依参数mode的权限来更改参数path 指定文件的权限
函数返回值:权限改变成功返回0,失败返回-1,错误返回errno
参数 | 说明 |
S_IRUSR | 所有者具有读权限 |
S_IWUSR | 所有者具有写权限 |
S_IXUSR | 所有者具有执行权限 |
S_IRGRP | 组具有读权限 |
S_IWGRP | 组具有写权限 |
S_IXGRP | 组具有执行权限 |
S_IROTH | 其他用户具有读权限 |
S_IWOTH | 其他用户具有写权限 |
S_IXOTH | 其他用户具有执行权限 |
eg1:将~/test/a.txt文件的权限设置为所有者可读可写,其他用户只读
#include
#include #include #include int main(){ printf("修改前 ~/test/a.txt 的权限:\n"); system("ls -l ~/test/a.txt"); chmod("/home/hanzhuan/test/a.txt",S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); printf("修改后 ~/test/a.txt 的权限:\n"); system("ls -l ~/test/a.txt"); return 0; } 运行结果:
所需头文件:#include
#include
函数功能:设置建立新文件时的权限掩码(但是返回的是原来的权限掩码)
函数原型:mode_t umask(mode_t mask);
函数传入值:4位8进制数
函数返回值:原先系统的权限掩码(umask值)
备注:建立文件时,该文件的真正权限为(0666-mask)
建立文件夹时,该文件夹的真正权限为(0777-mask)
值范围为0~7 开头的0表示8进制
eg1:设计一个程序,应用umask函数设置系统文件与目录的权限掩码.要求:新建文件的权限分别是0000和0222
/*设计一个程序,应用umask函数设置系统文件与目录的权限掩码*/ #include
#include #include #include int main(){ mode_t new_umask,old_mask; new_umask=0666; old_mask=umask(new_umask);//设置新权限掩码为0666(新文件权限为0000 新文件夹权限为0111) 返回旧权限 printf("系统原来的权限掩码是:%o\n",old_mask); printf("系统新的权限掩码是:%o\n",new_umask); printf("系统新的文件权限是:%o\n",0666-new_umask); printf("系统新的文件夹权限是:%o\n",0777-new_umask); system("touch file1"); system("mkdir dir1"); printf("创建了文件file1\n"); printf("创建了文件夹dir1\n"); new_umask=0444; old_mask=umask(new_umask);//设置新权限掩码为0444(新文件权限为0222 新文件夹权限为0333) printf("系统原来的权限掩码是:%o\n",old_mask); printf("系统新的权限掩码是:%o\n",new_umask); printf("系统新的文件权限是:%o\n",0666-new_umask); printf("系统新的文件夹权限是:%o\n",0777-new_umask); system("touch file2"); system("mkdir dir2"); printf("创建了文件file2\n"); printf("创建了文件夹dir2\n"); system("ls file1 -l"); system("ls -l | grep dir1"); system("ls file2 -l"); system("ls -l | grep dir2"); chmod("file2",S_IWUSR|S_IXOTH); printf("强制改为w-x:\n"); system("ls file2 -l"); return 0; } 运行结果:
强大的stat结构体
在使用这个结构体和方法时,需要引入:
struct stat这个结构体是用来描述一个linux系统文件系统中的文件属性的结构。
可以有两种方法来获取一个文件的属性:
1、通过路径:
int stat(const char *path, struct stat *struct_stat);
int lstat(const char *path,struct stat *struct_stat);
两个函数的第一个参数都是文件的路径,第二个参数是struct stat的指针。返回值为0,表示成功执行。
执行失败是,error被自动设置为下面的值:
EBADF: 文件描述词无效
EFAULT: 地址空间不可访问
ELOOP: 遍历路径时遇到太多的符号连接
ENAMETOOLONG:文件路径名太长
ENOENT:路径名的部分组件不存在,或路径名是空字串
ENOMEM:内存不足
ENOTDIR:路径名的部分组件不是目录
这两个方法区别在于stat没有处理字符链接(软链接)的能力,如果一个文件是符号链接,stat会直接返回它所指向的文件的属性;而lstat返回的就是这个符号链接的内容。这里需要说明一下的是软链接和硬链接的含义。我们知道目录在linux中也是一个文件,文件的内容就是这这个目录下面所有文件与inode的对应关系。那么所谓的硬链接就是在某一个目录下面将一个文件名与一个inode关联起来,其实就是添加一条记录!而软链接也叫符号链接更加简单了,这个文件的内容就是一个字符串,这个字符串就是它所链接的文件的绝对或者相对地址。
2、通过文件描述符
int fstat(int fdp, struct stat *struct_stat); //通过文件描述符获取文件对应的属性。fdp为文件描述符
下面是这个结构的结构
struct stat { mode_t st_mode; //文件对应的模式,文件,目录等 ino_t st_ino; //inode节点号 dev_t st_dev; //设备号码 dev_t st_rdev; //特殊设备号码 nlink_t st_nlink; //文件的连接数 uid_t st_uid; //文件所有者 gid_t st_gid; //文件所有者对应的组 off_t st_size; //普通文件,对应的文件字节数 time_t st_atime; //文件最后被访问的时间 time_t st_mtime; //文件内容最后被修改的时间 time_t st_ctime; //文件状态改变时间 blksize_t st_blksize; //文件内容对应的块大小 blkcnt_t st_blocks; //伟建内容对应的块数量 };
stat结构体中的st_mode 则定义了下列数种情况:
S_IFMT 0170000 文件类型的位遮罩 S_IFSOCK 0140000 scoket S_IFLNK 0120000 符号连接 S_IFREG 0100000 一般文件 S_IFBLK 0060000 区块装置 S_IFDIR 0040000 目录 S_IFCHR 0020000 字符装置 S_IFIFO 0010000 先进先出 S_ISUID 04000 文件的(set user-id on execution)位 S_ISGID 02000 文件的(set group-id on execution)位 S_ISVTX 01000 文件的sticky位 S_IRUSR(S_IREAD) 00400 文件所有者具可读取权限 S_IWUSR(S_IWRITE)00200 文件所有者具可写入权限 S_IXUSR(S_IEXEC) 00100 文件所有者具可执行权限 S_IRGRP 00040 用户组具可读取权限 S_IWGRP 00020 用户组具可写入权限 S_IXGRP 00010 用户组具可执行权限 S_IROTH 00004 其他用户具可读取权限 S_IWOTH 00002 其他用户具可写入权限 S_IXOTH 00001 其他用户具可执行权限
上述的文件类型在POSIX中定义了检查这些类型的宏定义:
S_ISLNK (st_mode) 判断是否为符号连接 S_ISREG (st_mode) 是否为一般文件 S_ISDIR (st_mode) 是否为目录 S_ISCHR (st_mode) 是否为字符装置文件 S_ISBLK (s3e) 是否为先进先出 S_ISSOCK (st_mode) 是否为socket
eg1:编写程序实现输出指定文件的大小、最后一次访问时间和最后一次修改时间
/*获取文件大小 最后一次访问时间 最后一次修改时间*/ #include
#include #include #include int main(){ struct stat buf; char a[100]; struct tm *p1,*p2; printf("输入文件完整路径+文件名:"); scanf("%s",a); stat(a,&buf); p1=localtime(&buf.st_atime);//获取当地时间 并按现在的时间日期来表示 p2=localtime(&buf.st_mtime);//struct tm *p=localtime(&time_t); tm强大结构体 printf("文件名:%s\n",a); printf("大 小:%d\n",buf.st_size); printf("最后一次访问时间: %d年%d月%d日 %d:%d:%02d\n",1900+p1->tm_year,p1->tm_mon+1,p1->tm_mday,p1->tm_hour,p1->tm_min,p1->tm_sec); printf("最后一次修改时间: %d年%d月%d日 %d:%d:%02d\n",1900+p2->tm_year,p2->tm_mon+1,p2->tm_mday,p2->tm_hour,p2->tm_min,p2->tm_sec); return 0; } 运行结果:
函数 | 作用 |
creat | 创建文件 |
open | 打开或创建文件 |
close | 关闭文件 |
read | 读文件 |
write | 写文件 |
lseek | 移动文件的读写位置 |
flock | 锁定文件或解除锁定(用于文件加建议性锁) |
fcntl | 文件描述符操作(用于文件加强制性锁) |
所需头文件:#include
#include
#include
函数功能:创建文件
函数原型:int creat(const char* pathname,mode_t mode);
函数传入值:建立文件的访问路径,用来设置新增文件的权限
参数mode见1.3linux文件权限
函数返回值:由内核返回一个最小可用的文件描述符,出错返回-1
eg1:编程实现在~/test/Io/目录下创建一个名为io.txt的文件,并将此文件的权限设置为所有者具有只读权限,最后显示此文件的信息。
/*c程序创建文件 并指定权限*/ #include
#include #include #include #include int main(){ int fd; fd=creat("/home/hanzhuan/test/IO/io.txt",S_IRUSR); system("ls /home/hanzhuan/test/IO/io.txt -l"); return 0; } 运行结果:
open函数说明:
所需头文件:#include
#include
#include
函数功能:打开文件(不存在创建文件)
函数原型:int open(const char * pathname,int flags);
int open(const char * pathname,int flags,mode_t mode);
函数传入值:建立文件的访问路径,用来设置新增文件的权限
建立文件的访问路径,指定访问文件的命令模式,用来设置新增文件的权限
函数返回值:由内核返回一个最小可用的文件描述符,出错返回-1
flag参数说明如下:
O_RDONLY:以只读模式打开
O_WRONLY:以写入模式打开
O_RDWR:以读写模式打开
O_APPEND:在文件尾写入数据
O_TRUNC:设置文件的长度0,并舍弃现存的数据
O_CREAT:建立文件,可用mode参数设置访问权限
O_EXCL:与O_CREAT一起使用,若所建立的文件已存在,则打开失败
close函数说明如下:
所需头文件:#include
函数功能:关闭文件
函数原型:int close(int fd);
函数传入值:整型
函数返回值:文件顺利关闭返回0,发生错误返回-1
备注:当一个进程终止时,它所有已打开的文件都由内核自动关闭
虽然如此,但:还是建议人工关闭文件,并检查返回值
eg:在/home/hanzhuan/test/IO目录下以可读写方式打开一个文件,若不存在创建此文件;若存在,清空后关闭
(原来目录下有io1.txt且有内容 无io2.txt)
/*打开文件*/ #include
#include /*system*/ #include /*open*/ #include /*close*/ int main(){ int fd; if((fd=open("/home/hanzhuan/test/IO/io1.txt",O_CREAT|O_TRUNC|O_WRONLY,0600))<0){ /*O_CREAT:b不存在建立文件 O_TRUNC:设置文件的长度0,并舍弃现存的数据 O_WRONLY:以写入模式打开 0600:所有者rw权限 出错返回-1<0 */ perror("打开文件出错!"); exit(1); }else{ printf("打开(创建)文件 io1.txt ,文件描述符为:%d\n",fd); } if(close(fd)<0){ perror("关闭文件出错!"); exit(1); } system("ls /home/hanzhuan/test/IO/io1.txt -l"); return 0; } 运行结果: