C++ Linux——文件I/O操作和系统函数讲解(1)

文章是在牛客学习高薪求职课程,高并发服务器时所写 
因为篇幅太长,将分成两篇博客

目录

一、标准c库和Linux系统I/O函数

 二、虚拟地址空间

三、文件描述符 

四、系统I/O函数以及讲解 

1.open函数打开一个文件:

2.open函数打开并创造文件 

3.read、write函数:

4.lseek函数 

5.state,lstate函数 

模拟实现ls指令  

一、标准c库和Linux系统I/O函数

 1.标准c库是跨平台的函数,能调用Linux的IO函数,相当于优先级更高
2.标准c库在读写时都有缓冲区,当下列几种情况才会将 数据从内存刷新到磁盘 

(1)刷新缓冲区:fflush

( 2).缓冲区已满 
(3).正常关闭文件 a.fclose b.return(main函数) c.exit(main函数 
但是Linux IO函数没有缓冲区,相对来说效率更慢

 二、虚拟地址空间

三、文件描述符 

1.进程控制块(PCB)中的文件描述符表前三行放置 标准输入 标准输出 标准错误  固定不可改变 0 -> STDIN_FILENO                       1 -> STDOUT_FILENO 2 -> STDERR_FILENO (默认大小是1024),指向当前终端
2.同一个文件被同时打开多次,文件指针定位的文件描述符都不一样
3. 每打开一个新文件, 则占用一个文件描述 符,而且是空闲的最 小的一个文件描述符 
4.Linux文件操作是通过文件描述符所对应那个文件去操作

四、系统I/O函数以及讲解 

1.int open(const char *pathname, int flags);

2.int open(const char *pathname, int flags, mode_t mode);

3.int close(int fd);

4.ssize_t read(int fd, void *buf, size_t count);

5.ssize_t write(int fd, const void *buf, size_t count);

6.off_t lseek(int fd, off_t offset, int whence);

7.int stat(const char *pathname, struct stat *statbuf);

8.int lstat(const char *pathname, struct stat *statbuf);

1.open函数打开一个文件:

#include <sys/types.h>

#include <sys/stat.h>
#include <fcntl.h>

    //打开一个已经存在的文件
    int open(const char *pathname, int flags);
          pathname:文件路径
          flags:对文件的权限设置还有其他设置
          O_RDONLY, O_WRONLY, or O_RDWR 只读,只写,可读可写,通常是互斥的
          返回值: open(), openat(), and creat() return the new file descriptor, or -1 if an
                  error occurred(in which case, errno is set appropriately)
          errno:属于Linux函数库里面的一个全局变量,记录最近的错误号 每个错误都有一个错误号

/*
 
    #include <stdio.h>
    void perror(const char *s); 作用:打印errno对应的错误描述
        s:用户描述,比如hello,最终输出的内容是hello:xxx(最终的错误信息)
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
    int fd = open("a.txt",O_RDONLY);

    if(fd == -1){
        perror("open");
    }

    close(fd);
    return 0;
}

2.open函数打开并创造文件 

头文件:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

    int open(const char *pathname, int flags, mode_t mode);

    pathname:文件路径
    flags:对文件的权限设置还有其他设置
        必选项:O_RDONLY, O_WRONLY, or O_RDWR 只读,只写,可读可写,通常是互斥的
        可选项:O_CREAT:文件不存在,创建文件
    flags:int类型,每一位都是一个标志位
    mode:八进制数,表示创造出的文件的操作权限
    最终的权限:mode &~umask  umask的作用是抹去某一些权限

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    int fd = open("create.txt", O_RDWR | O_CREAT, 0777);
    
    if(fd == -1){
        perror("open");
    }

    close(fd);
    return 0;
}

3.read、write函数:

 头文件:#include <unistd.h>
函数原型:ssize_t read(int fd, void *buf, size_t count);
    参数:
        fd:文件描述符,open得到,通过文件描述符操作某个文件
        buf:读取数据存放的地方,一般是数组的地址(传出参数)
        count:指定的数组大小
    返回值:
        成功:>0返回实际读取到的字节数
             =0 文件已经读取完成
        失败:-1,并且设置error


    #include <unistd.h>
    ssize_t write(int fd, const void *buf, size_t count);
        fd:文件描述符,open得到,通过文件描述符操作某个文件
        buf:要往磁盘写入的数据
        count:写入数据实际的大小
    返回值:
        成功:返回写入的字节数
        失败:返回-1,并设置error

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
    int srcfd = open("english.txt",O_RDONLY);
    if(srcfd==-1){
        perror("open");
        return -1;
    }

    int destfd = open("cpy.txt",O_WRONLY | O_CREAT,0664);

    char buf[1024] = {0};
    int len = 0;

    while((len = read(srcfd,buf,sizeof(buf)))>0 ){
        write(destfd,buf,len);
    }
    close(srcfd);
    close(destfd);
    return 0;
}

4.lseek函数 

 标准c库
    #include <stdio.h>
    int fseek(FILE *stream, long offset, int whence);
    
    Linux系统函数
    #include <sys/types.h>
    #include <unistd.h>

    off_t lseek(int fd, off_t offset, int whence);

        参数:
            fd:文件描述符
            offset:偏移量
            whence:
                SEEK_SET:设置文件指针偏移量
                SEEK_CUR:设置偏移量:当前位置+第二个参数offset的值
                SEEK_END:设置偏移量:文件大小 + 第二个参数offset的值
        返回值:返回文件指针位置
        作用:
            1.移动文件指针到头文件
            lseek(fd,0,SEEK_SET);

            2.获取当前文件指针位置:
            lssek(fd,0,SEEK_CUR)

            3.获取文件长度
            lseek(fd,0,SEEK_END)

            4.拓展文件的长度:如当前文件10b——》110b,增加100个字节
            lseek(fd,100,SEEK_END)
            注意:需要写入一次数据

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include<stdio.h>
int main()
{
    int fd = open("hello.txt",O_RDWR);

    if(fd ==-1){
        perror("open");
    }

    //拓展文件长度
    int ret = lseek(fd,100,SEEK_END);

    //写入一个空字符串
    write(fd," ",1);
    if(ret==-1)
    {
        perror("lseek");
        return -1;
    }
    close(fd);
    return 0;
}

5.state,lstate函数 

 #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>

    int stat(const char *pathname, struct stat *statbuf);
        作用:获取文件相关的信息
        参数:
            pathname:路径
            statbuf:结构体变量,传出参数,用于保存获取到的文件的信息
        返回值:
            成功:返回0
            失败:返回-1 设置errno

    int lstat(const char *pathname, struct stat *statbuf);
        作用:获取文件软连接的信息 软连接:通过命令:ln -s a.txt b.txt生成的b.txt 就是指向a的软连接 
        参数:
            pathname:路径
            statbuf:结构体变量,传出参数,用于保存获取到的文件的信息
        返回值:
            成功:返回0
            失败:返回-1 设置errno

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
    struct stat statbuf;

    int ret = stat("a.txt", &statbuf);

    if(ret == -1){
        perror("stat");
        return -1;
    }

    printf("size:%ld\n",statbuf.st_size);
    return 0;

}

模拟实现ls指令 

//模拟实现ls -l指令
//-rw-rw-r-- 1 china china 11 7月   1 21:54 a.txt
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include<stdio.h>
#include<pwd.h>
#include<grp.h>
#include<time.h>
#include<string.h>
int main(int argc,char * argv[])
{
    //判断输入参数是否正确
    if(argc < 2){
        printf("%s filename",argv[0]);
        return -1;
    }

    //通过stat函数获取用户传入的文件的信息
    struct stat st;
    int ret = stat(argv[1],&st);

    if(ret == -1){
        perror("stat");
        return -1;
    }

    //获取文件类型和文件权限

    char perms[11] ={0}; //用于保存文件类型和文件权限

    switch(st.st_mode & __S_IFMT){
        case __S_IFLNK:
            perms[0] = '1';
            break;
        case __S_IFDIR:
            perms[0] = 'd';
            break;
        case __S_IFREG:
            perms[0] = '-';
            break;
        case __S_IFBLK:
            perms[0] = 'b';
            break;
        case __S_IFCHR:
            perms[0] = 'c';
            break;
        case __S_IFSOCK:
            perms[0] = 's';
            break;
        case __S_IFIFO:
            perms[0] = 'p';
            break;
        default:
            perms[0] = '?';
    }

    //判断文件访问权限

    //文件所有者
    perms[1] =(st.st_mode & S_IRUSR) ? 'r':'-';
    perms[2] =(st.st_mode & S_IWUSR) ? 'w':'-';
    perms[3] =(st.st_mode & S_IXUSR) ? 'x':'-';

    //文件所在组
    perms[4] =(st.st_mode & S_IRGRP) ? 'r':'-';
    perms[5] =(st.st_mode & S_IWGRP) ? 'w':'-';
    perms[6] =(st.st_mode & S_IXGRP) ? 'x':'-';

    //其他人
    perms[7] =(st.st_mode & S_IROTH) ? 'r':'-';
    perms[8] =(st.st_mode & S_IWOTH) ? 'w':'-';
    perms[9] =(st.st_mode & S_IXOTH) ? 'x':'-';

    //硬链接数
    int linkNum = st.st_nlink;

    //文件所有者
    char * fileuser = getpwuid(st.st_uid)->pw_name;

    //文件所在组
    char * fileGrp = getgrgid(st.st_gid)->gr_name;

    //文件大小
    long int fileSize  = st.st_size;

    //获取修改时间
    char * time = ctime(&st.st_mtime);

    char mtime[512] ={0};
    strncpy(mtime,time,strlen(time)-1);//为了去掉时间转换后的换行

    char buf[1024];
    sprintf(buf,"%s %d %s %s %ld %s %s",perms,linkNum,fileuser,fileGrp,fileSize,mtime,argv[1]);
    printf("%s\n",buf);
    return 0;
}


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值