UNIX环境高级编程-第4章- 文件和目录 - 三

前言

       在Linux系统中利用ln指令产生链接,Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link)。默认情况下,ln命令产生硬链接。

硬链接

       硬链接是一种通过文件系统的inode链接产生,硬链接可以认为是一个指针,指向文件inode的指针,系统并不为它重新分配inode。所以存在多个文件指向同一个inode节点,添加硬链接,会使文件的链接数增加。删除多个链接中其中一个连接并不影响inode和其它的连接,只有当最后一个连接被删除后,文件的数据块及目录的连接才会被释放。

       硬链接有两个限制:

不能创建跨文件系统的硬链接。

只有超级用户才可以创建目录链接,一般用户不允许创建。(跟系统有关)

硬链接的使用

/************* 
 * 硬链接指令ln使用方式如下: 
 * ln existingfile newfile 
 * 说明: 
 * 为当前存在的文件existingfile创建新的硬链接,链接文件名为newfile. 
*/  

举例说明:

/********  
 * 举例子说明:  
 * 列出当前文件存在的信息,包括关键inode节点信息:  
********/  
 $ ls -il file1 file2  
 10890904 -rw-rw-r-- 1  file1  
 10890903 -rw-rw-r-- 1  file2  
 $ ln file1 hardlink  
 $ ls -il file1 file2 hardlink  
 10890904 -rw-rw-r-- 2  file1  
 10890903 -rw-rw-r-- 1  file2  
 10890904 -rw-rw-r-- 2  hardlink  
 $ cat file1 hardlink  
 Hello, this is the file1.  
 Hello, this is the file1.   
 $ rm file1  
 $ ls -il file2 hardlink  
 10890903 -rw-rw-r-- 1  file2  
 10890904 -rw-rw-r-- 1  hardlink  
 $ cat hardlink  
 Hello, this is the file1.  
 $ rm hardlink  
 $ cat hardlink  
 cat: hardlink: No such file or directory  <span style="font-family: Arial, Helvetica, sans-serif;"> </span>

      由上面例子我们可以看出,创建硬链接之前,file1 显示的链接数目为1,创建链接后hardlink之后,file1和hardlink的链接数目都变为2,但是file1和hardlink的inode号码是一样的,说明创建硬链接并不会新建inode节点,只会增加链接数。因此,创建硬链接使多个文件指向同一个inode节点,它们具有同样的inode索引节点号和文件属性。删除其中任何一个链接,并不会删除原始文件信息,如rm file1 ,只是删除一个链接指针,链接数同时减一,只有将所有指向同一个inode节点的链接指针删除,也即链接数减为0时,内核才会把文件内容从磁盘上删除。

4.16 符号链接

       可以在不同文件系统中创建符号链接,任何用户可以创建指向目录的符号链接。给ln指令加上-s选项,则是创建符号链接,它是创建一个独立的文件,而这个文件的数据操作会指向它所链接的那个文件的文件名。当所链接的源文件被删除时,符号链接则打不开该文件,即链接失效。

       举例说明:

/************* 
 * 符号链接指令ln使用方式如下: 
 * ln -s existingfile newfile 
 * 说明: 
 * 为当前存在的文件existingfile创建新的符号链接,链接文件名为newfile. 
 * 举例子说明: 
 * 列出当前文件存在的信息,包括关键inode节点信息: 
*/  
  $ ls -il file1 file2  
  10890912 -rw-rw-r-- 1  file1  
  10890903 -rw-rw-r-- 1  file2  
  $ ln -s file1 symblink  
  $ ls -il file1 file2 symblink  
  10890912 -rw-rw-r-- 2  file1  
  10890903 -rw-rw-r-- 1  file2  
  10890907 lrwxrwxrwx 1  symblink -> file1  
  $ cat file1 symblink  
  Hello, this is the file1.  
  Hello, this is the file1.  
  $ rm file1  
  $ ls -il file2 symblink  
  10890903 -rw-rw-r-- 1  file2  
  10890907 lrwxrwxrwx 1  symblink -> file1  
  $ cat symblink  
  cat: symblink: No such file or directory  
 

创建符号链接时,会分配新的inode节点,即是新的文件,链接数目不会增加。

可以得到以下全部结论:

删除硬连接hardlink,对file1无影响;

删除原文件file1,对硬连接hardlink没有影响,符号连接symblink失效;

同时删除原文件file1,硬连接hardlink,整个文件会真正的被删除。

4.17 symblink和readlink函数

/********** 
 * 函数功能:创建一个符号链接。 
 * 返回值:若成功则返回0,若出错则返回-1; 
 * 函数原型: int symblink(const char *actualpath, const char *sympath);  
 */  
/********* 
 * 说明 
 * 该函数创建一个指向actualpath的新目录项sympath,创建符号链接时,并不要求 
 * actualpath存在,也可以位于不同的文件系统。 即对于一个不存在的文件或者目录,也可* 以创建符号链接,但是此时无法打开这个链接。
 */  

/****************** 
 * 函数功能:打开符号链接 
 * 返回值:若成功则返回读到buf中的字节数,若出错则返回-1; 
 * 函数原型: ssize_t readlink(const char *pathname, char *buf, size_t bufsize); */ 

4.18  文件时间 

 /* 根据stat的结构可以知道,文件有三种时间: 
 * st_atime     最后访问时间,即最后访问文件的时间    ls -u
 * st_mtime     最后修改时间,即修改文件内容的时间     默认ls
 * st_ctime     最后更改时间,即更改inode节点的时间    ls –c
* 更改文件的访问权限,用户ID,链接数都可以影响到inode
 * ****/  

 4.19  utime函数 

/* 函数功能:更改文件访问时间和文件修改时间; 不能更改状态时间 st_ctime  ,当调用
* utime函数时,此字段将被自动更新
 * 返回值:若成功则返回0,若出错则返回-1; 
 * 函数原型:  int utime(const char *pathname, const struct utimbuf *times); 
 * 其中结构体struct utimbuf 定义如下: 
 *      struct utimbuf
*      { 
 *               time_t actime;// access time  
 *                time_t modtime;// modification time 
 *      }; 
 *  参数说明: 
 *  pathname是要更改时间的文件; 
 *  times若为空指针,则表示设置为当前时间; 
 *  若times非空指针,则设置为所指向结构体中的对应值; 
 *  ********/  

测试程序:功能是更改文件 ,但是文件时间不改变。

#include "apue.h"  
#include <fcntl.h>  
#include <utime.h>  
  
int main(int argc, char *argv[])  
{  
    int i,fd;  
    struct stat statbuf;  
    struct utimbuf timebuf;  
  
    for(i=1;i<argc;i++)  
    {  
         //获取文件的当前时间
        if(stat(argv[i],&statbuf) < 0){  
            err_ret("%s:stat error.\n",argv[i]);  
            continue;  
        }  
         //将文件长度截短为0 ,但不更改文件的访问时间和修改时间
        if((fd = open(argv[i],O_RDWR | O_TRUNC)) < 0){  
            err_ret("%s:open error.\n",argv[i]);  
            continue;  
        }  
        close(fd);  
        timebuf.actime = statbuf.st_atime;  
        timebuf.modtime = statbuf.st_mtime;  
         //把时间更改为之前通过 stat函数获得的时间,即文件虽然动了但是时间没变
        if(utime(argv[i],&timebuf) < 0){  
            err_ret("%s:utime error.\n",argv[i]);  
            continue;  
        }  
    }  
    exit(0);  
}  

目录基本操作

目录的基本操作包括创建目录 mkdir 、删除目录 rmdir 、打开目录opendir、读取目录readdir、关闭目录closedir等操作,如下说明:

4.20 mkdir 和 rmdir 函数

用 mkdir 函数创建目录,用 rmdir 函数删除目录

/*********** 
 * 目录创建 
 * 函数功能:创建一个空目录 
 * 返回值:若成功则返回0,若出错则返回-1; 
 * 函数原型: 
 * #include <sys/stat.h> 
 * int mkdir(const char *pathname, mode_t mode); 
 * 说明: 
 * 此函数创建一个新的空目录,其中.和..目录项是自动创建的。 
 * 所指定的文件访问权限mode由进程的文件模式创建屏蔽字修改。 
 * 
 * 删除空目录 
 * 函数功能:删除一个空的目录 
 * 返回值:若成功则返回0,若出错则返回-1; 
 * 函数原型: 
 * #include <unistd.h> 
 * int rmdir(const char *pathname); 
 * 说明: 
 * 如果调用该函数使目录的链接数为0,且没有其他进程打开该目录,则释放该目录空间。 
 * 若链接数为0,此时有进程打开该目录,在进程关闭前不会释放目录空间。 
 * ***************/  

 4.21 读目录

 /* 
 * 1、 函数功能:读取目录 
 *  返回值:若成功返回指针,若在目录结尾或出错则返回NULL; 
 *  函数原型: 
 *  #include <unistd.h> 
 *  #include <dirent.h> 
 *  struct dirent *readdir(DIR *dp); 
 
* 2、打开目录opendir  
 *  函数功能:打开一个目录; 
 *  返回值:若成功返回一个目录指针,若出错则返回NULL指针; 
 *  函数原型: 
 *  #include <sys/types.h> 
 *  #include <dirent.h> 
 *  DIR *opendir(const char *pathname); 
 
 * 
 * 3、重设与dp关联的目录中的位置 
 * 
 *  函数功能:重设与dp关联的在目录中的位置; 
 *  没有返回值; 
 *  函数原型: 
 *  #include <sys/types.h> 
 *  #include <dirent.h> 
 *  void rewinddir(DIR *dp); 
 * 
 * 4、dp关联的在目录的当前位置return current location in directory stream. 
 * 
 * 函数功能:获取与dp关联的在目录中的当前位置; 
 *  返回值:若成功返回与dp关联的在目录中的当前位置,若出错返回-1; 
 *  函数原型: 
 *  #include <dirent.h> 
 *  off_t telldir(DIR *dp); 
 * 
 * 5、The seekdir() function sets the location in the  directory 
 *    stream  from  which  the  next  readdir() call will start. 
 *    seekdir() should  be  used  with  an  offset  returned  by telldir(). 
 * 
 *   函数功能:设置下一个readdir调用在目录的位置 
 *    无返回值 
 *    函数原型: 
 *    #include <dirent.h> 
 *    void seekdir(DIR *dp, off_t offset); 
 * 
 * 6、关闭一个已打开的目录 
 * 
 *  函数功能:关闭一个已打开的目录 
 *  返回值:若成功返回0,若出错返回-1; 
 *  函数原型: 
 *  #include <sys/types.h> 
 *  #include <dirent.h> 
 *  int closedir(DIR *dp); 
 *  **********************************/  
目录信息结构
/************************************ 
 * struct dirent结构信息 
 * *******/  
   struct dirent  
    {  
        long d_ino;                 /* inode number */  
        off_t d_off;                /* offset to this dirent */  
        unsigned short d_reclen;    /* length of this d_name */  
        char d_name [NAME_MAX+1];   /* file name (null-terminated) */  
    };  */

4.22 chdir、fchdir、getcwd 函数

/************************* 
 * 更改当前工作目录。 
 * 函数功能:更改当前的工作目录; 
 * 返回值:若成功则返回0,若出错则返回-1; 
 * 函数原型: 
 * #include <unistd.h> 
 * int chdir(const char *pathname); 
 * int fchdir(int filedes); 
 * 说明: 
 * 这两个函数分别用pathname或打开文件描述符来指定当前的工作目录。 
 * **********/  
/************* 
 * 函数功能:获取当前工作目录的绝对路径 
* 返回值:若成功则返回buf,若出错则返回NULL; 
 * 函数原型: 
 * #include <unistd.h> 
 * char *getcwd(char *buf, size_t size); 
* 说明:buf存储绝对路径,长度size应该最够容纳绝对路径再加上一个null终止字符,否* 则返回出错。
 * ***************/  


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值