6.unlink

6.1 头文件包含

#include <unistd.h>

6.2 接口原型

int unlink(const char *pathname);

6.3 参数介绍

pathname 文件名

6.4 返回值

成功返回0,错误返回-1并且设置errno

 

6.5 用途

删除一个文件的目录项并减少它的链接数,如果想通过这个函数来删除一个文件,你必须拥有这个文件所属目录的读写权限

(1)如果是符号链接,则删除符号链接

(2)如果是硬链接,硬链接数减1,当减为0时,释放数据块和inode

(3)如果文件硬链接为0时,但有进程已打开该文件,并持有文件描述符,则等进程关闭该文件时,kernel才真正去删除该文件

6.6 demo

#include <iostream>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string>

#include <fcntl.h>

#include <sys/types.h>

using namespace std;

 

int main(){

// 创建临时文件

    int fd = open("file_tmp_unlink", O_CREAT | O_RDWR, 0664);

    if(fd == -1){

        perror("open");

        exit(1);

    }  

// unlink减少硬链接数

    if(unlink("file_tmp_unlink") == -1){

        perror("unlink");

        exit(1);

}  

 

    string str = "As long as you love me\n";

    write(fd, str.data(), str.length());

 

    if(lseek(fd, 0, SEEK_SET) == -1){

        perror("lseek");

        exit(1);

    }  

    char buf[100];

    read(fd, buf, sizeof(buf));

    string res = buf;

    write(1, res.data(), res.length());

    close(fd);

 

    return 0;

}

fe479ee1adbd24f080cbe3a9ef18e7d.png

7.opendir

7.1 头文件包含

#include <sys/types.h>

#include <dirent.h>

7.2 接口原型

DIR *opendir(const char *name);

7.3 参数介绍

name    目录名字

7.4 返回值

成功打开目录时返回DIR结构体指针,该结构是一个内部结构,保存所打开的目录信息,作用类似于FILE结构。函数出错时返回NULL

7.5 用途

打开一个目录文件

 

8.readdir

8.1 头文件包含

#include <dirent.h>

8.2 接口原型

struct dirent *readdir(DIR *dirp);

8.3 参数介绍

传入的是一个目录指针,类型是DIR结构体。

8.4 返回值

返回的是一条记录项,类型是dirent结构体

dirent结构体原型为

struct dirent {

ino_t                 d_ino;         //此目录进入点的inode 

off_t                  d_off;       // 目录文件开头至此目录进入点的位移   

unsigned short   d_reclen;         // d_name 的长度,不包含

unsigned char   d_type;          // d_name 所指的文件类型

char                  d_name[256]; // 文件名

  };

8.5 用途

读取目录

8.6 DEMO 获得指定目录中的普通文件个数

核心递归函数

int get_filesNum(const char *file_name){

    // 获取dir目录指针

    DIR * dir = opendir(file_name);

// 文件个数计数变量   

int sum = 0;

// 目录打开失败

    if(dir == NULL){

        perror("open file error"); 

        exit(1);

    }else{

   

        struct dirent * ptr = NULL;

      // 遍历目录中的文件

        while((ptr = readdir(dir)) != NULL){

               

            if(!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, "..")){

                continue;

            }else if(ptr->d_type == DT_DIR){

      // 递归读取目录

                string dir_name = file_name;

                dir_name += "/";

                dir_name += ptr->d_name;

                sum += get_filesNum(dir_name.data());

 

            }else if(ptr->d_type == DT_REG){

 

                ++sum;

            }

 

        }

 

    }  

//关闭当前目录

closedir(dir);

//返回当前目录及子级目录的普通文件总数

    return sum;

}

 

9.dupdup2

9.1 头文件包含

#include <unistd.h>

9.2 接口原型

int dup(int oldfd);

int dup2(int oldfd, int newfd);

9.3 参数介绍

(1) dup

oldfd     文件描述符

(2) dup2

oldfd     原始文件描述符

newfd   复制到的文件描述符,若此文件描述符被占用,将关闭该文件描述符所占用的文件,再把oldfd的文件描述符复制到newfd

9.4 返回值

(1) dup

返回的是文杰描述符表中没有被占用的最小的文件描述符

(2) dup2

返回复制的文件描述符

9.5 用途

复制文件描述符号,可以使多个文件描述符(fd)指向同一个文件指针,操作同一个文件

9.6 DEMO

Description

创建一个文件, 描述符为fd,首先用dup把新的文件描述符fd2指向 fd指向的文件,分别向fdfd2指向的文件写入信息。用dup2 fd指向文件描述符为1的文件指针,再用dup2fd2指向fd指向的文件,第一次关闭fd所指向的文件,第二次dup2再关闭fd2指向的文件,第二次dup2后,创建出的新的文件已经没有文件描述符所占用。最后向fd,fd2指向的文件输出信息,因为文件描述符1是标准输出,指向控制台终端,所以最后的信息将输出到控制台。

Code

#include <iostream>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <string>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

 

using namespace std;

 

void write_something(const int & fd, const int & fd2){

    // prepare two strings for writing

    string str = "As long as you love me.....\n";

    string str2 = "I like to make myself believe that I can make it!\n";

    // write str to the pointer file of fd

    write(fd, str.data(), str.length());

    // write str2 to the pointer file of fd2

    write(fd2, str2.data(), str2.length());

}

 

int main(){

 

    int fd = open("dup_test.txt", O_CREAT | O_APPEND | O_RDWR, 0664);

    // dup fd->fd2

    int fd2 = dup(fd);

    // show nums of fd and fd2

    cout << "fd: " << fd << endl;

    cout << "fd2: " << fd2 << endl;

    // write something

    write_something(fd, fd2);

    // dup2 1->fd, fd point the file of 1

    fd = dup2(1, fd);

    // dup2 1->fd2, fd2 point the file of fd

    fd2 = dup2(fd, fd2);

    // show nums of fd and fd2

    cout << "fd: " << fd << endl;

    cout << "fd2: " << fd2 << endl;

    // write something 

    write_something(fd, fd2);

    close(fd);

    close(fd2);

 

    return 0;

}

10.fcntl函数

10.1 头文件包含

#include <unistd.h>

#include <fcntl.h>

10.2 接口原型

(1) int fcntl(int fd, int cmd);

(2) int fcntl(int fd, int cmd, long arg);

(3) int fcntl(int fd, int cmd, struct flock * lock);

10.3 参数介绍  

fd   文件描述符

cmd      操作标志,用途中将详细介绍

arg 文件状态标记

10.4 返回值

返回值依赖于传入的参数的使用操作,失败时返回-1

关于设置的操作成功时统一返回0

10.5 用途

根据文件描述符来操作文件的状态

ps:à为取值符

(1)复制一个现有的描述符 cmd à F_DUPFD, 使用原型(1)

(2)获得/设置文件描述符标记 cmd à{F_GETFD, F_SETFD}, 使用原型(1)

(3)获得/设置文件状态标记

使用原型(2)

cmdà{F_GETFD, F_SETFD}

F_GETFLà{O_RDONLY, O_WRONLY, 0_RDWR, O_EXEC, O_SEARCH, O_APPEND, O_NOBLOCK}

F_SETFLà{O_APPEND, O_NONBLOCK}

(4)获得/设置异步I/O所有权 cmdà{F_GETOWN, F_SETOWN},使用原型(1)

(5)获得/设置记录锁 cmdà{F_GETLK, F_SETLK, F_SETLKW}

 

10.6 DEMO

开始时以只写方式打开文件,向文件写入数据,新的数据将覆盖原来的数据;使用fcntl将文件描述符fd对应的文件标志状态增加追加写,再次向fd指向的文件写入新的数据,数据将在旧的数据末尾追加写入

#include <iostream>

#include <fcntl.h>

#include <unistd.h>

#include <string>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

 

using namespace std;

 

int main(){

    int fd;

    int flag;

    // test strings

    string str1 = "I like to make myself believe that I can make it!\n";

    string str2 = "Hello world! Hello my friends!\n";

 

    //open the file that only can write

    fd = open("test.txt", O_WRONLY);

    if(fd == -1){

        perror("open");

        exit(1);

    }  

    // input new message for the file and cover the old message

    if(write(fd, str1.data(), str1.length()) == -1){

        perror("write");

        exit(1);

    }  

 

    // use F_GETFL to get the flag of the file status

    flag = fcntl(fd, F_GETFL, 0);

    if(flag == -1){

        perror("fcntl");

        exit(1);

    }  

 

    // set file status flag of O_APPEND

    flag |= O_APPEND;

 

    // change the file status that set it for append write

    if(fcntl(fd, F_SETFL, flag) == -1){

        perror("fcntl -- append write");

        exit(1);

    }

    // input the message again, the new message will show append the old message

    if(write(fd, str2.data(), str2.length()) == -1){

        perror("write  again");

        exit(1);

    }

 

    close(fd);

 

    return 0;

}