Linux-IO中的open、read、write、lseek、stat、lstat

首先说明一点,这些所有的Linux的IO系统调用函数的头文件都不需要自己死记硬背的,可以通过查阅man手册来查看.

Linux系统IO用法一般通过man 2 xx来查看

标准C库系统IO一般使用man 3 xx来查看

这里既然提到了,那就简单说下Linux系统io和标准库io的主要区别:

Linux系统io和标准C库io的主要区别

1.标准C库io相较于linux的io多了一个io缓冲区,用来暂时存储数据.所以通常比linux的io操作更靠谱安全,效率更高。但是在网络通信方便,由于多了一个io缓冲区,所以考虑效率问题,大部分还是选择的Linux的IO中的socket(tcp udp)来进行.

2.标准C库io使用与几乎目前所有的主流操作系统:Windowns、Linux等等

下列所有的Linux系统IO调用函数,我都使用了实例可运行的代码来进行讲解,上面的笔记也是我一个一个总结出来的,希望大家结合起来看,能帮到大家

open

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

        参数:
            1.要打开的文件路径
            2.设置文件的权限:O_RDONLY, O_WRONLY, or O_RDWR,这三种方式互斥
        返回值:整数型的文件描述符或者-1
        perror:标准库IO中描述错误的系统调用函数
        void perror(const char *s); //输出错误信息 :xxxx

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

参数:
   @param1:要创建的文件的路径
   @param2:文件的操作权限 (比选项):O_RDONLY, O_WRONLY, or O_RDWR,这三种方式互斥
                                                                   可选项:O_CREAT 文件不存在就创建新文件
  @param3:八进制的数,表示用户对创建的新的文件的操作权限,比如:0775
                最终权限: mode & ~umask
                0777(三通道:读写可执行都打开) umask:0002-> ~umask:0777-0002=0775
                0777:   111111111
            &   0775:   111111101
                        111111101->0775
                uamsk作用:抹去某些权限,让创建的文件权限更加合理

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

/*
**********************************************************
    //主要用来打开已经存在的文件
    int open(const char *pathname, int flags);
        参数:
            1.要打开的文件路径
            2.设置文件的权限:O_RDONLY, O_WRONLY, or O_RDWR,这三种方式互斥
        返回值:整数型的文件描述符或者-1
        perror:标准库IO中描述错误的系统调用函数
        void perror(const char *s); //输出错误信息 :xxxx
***********************************************************
    int open(const char *pathname, int flags, mode_t mode);
    参数:
        @param1:要创建的文件的路径
        @param2:文件的操作权限 (比选项):O_RDONLY, O_WRONLY, or O_RDWR,这三种方式互斥
                可选项:O_CREAT 文件不存在就创建新文件
        @param3:八进制的数,表示用户对创建的新的文件的操作权限,比如:0775
                最终权限: mode & ~umask
                0777(三通道:读写可执行都打开) umask:0002-> ~umask:0777-0002=0775
                0777:   111111111
            &   0775:   111111101
                        111111101->0775
                uamsk作用:抹去某些权限,让创建的文件权限更加合理
***********************************************************
*/

int main()
{
    int fd = open("./a.txt",O_RDWR | O_CREAT, 0777); //没有文件就创建文件
    if(fd == -1)
    {
        perror("open");
    }
    else
    {
        printf("open sucefully!\n");
    }
    close(fd);
    return 0;
}

read和write

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
/*
    ssize_t read(int fd, void *buf, size_t count);
    参数:
        @param1:文件描述符,open得到,可以通过这个文件描述符对文件进行操作
        @param2:缓冲区,读取数据存放的地方(传出参数)
        @param3:指定的数组大小
    返回值:
            成功: 
                >0 返回实际读取到的字节数目
                =0:文件以及读完了
            失败:返回-1,并且设置errno

    ssize_t write(int fd, const void *buf, size_t count);
    参数:
        @param1:文件描述符,open得到,可以通过这个文件描述符对文件进行操作
        @param2:要往磁盘写入的数据,数据
        @param3:指写的数据实际的大小
    返回值:
            成功: 
                >0 返回实际写入的字节数目
            失败:返回-1,并且设置errno
*/
int main()
{
    int fd1 = open("./english.txt",O_RDONLY);
    if(fd1 == -1)
    {
        perror("open fd1");
        exit(-1);
    }
    //创建一个新的拷贝文件
    int fd2 = open("result.txt",O_RDWR | O_CREAT,0664);
    if(fd2 == -1)
    {
        perror("open and create fd2");
        exit(-1);
    }
    //读
    char read_buff[1024] = {0};
    int len = 0;
    while((len = read(fd1,read_buff,sizeof(read_buff))) > 0) 
    {
        write(fd2,read_buff,len); //读到多少写多少
    }
    close(fd1);
    close(fd2);
}

lseek

#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
Linux系统函数
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
    参数:
        fd:通过open得到的文件描述符
        offset:偏移量
        whence:
            SEEK_SET
                设置文件指针的偏移量
            SEEK_CUR
                设置偏移量:当前位置 + 第二个参数offset的值
            SEEK_END
                设置偏移量:文件的大小 + 第二个参数offset的值
    作用:
        1.移动文件指针到文件头
            lseek(fd,0,SEEK_SET);
        2.获取当前文件指针的位置
            lseek(fd,0,SEEK_CUR);
        3.获取文件长度
            lseek(fd,0,SEEK_END);
        4.扩展文件的长度,假如当前文件10b,增加100b
            lseek(fd,100,SEEK_END);
            如果要想扩展文件,移动了指针还需要在后面写入空数据
    返回值:
        返回文件指针的位置

标准库fseek
       #include <stdio.h>
       int fseek(FILE *stream, long offset, int whence);

*/
int main()
{   
    int fd = open("hello.txt",O_RDWR);
    if(fd == -1)
    {
        perror("open");
        exit(-1);
    }

    int ret = lseek(fd,100,SEEK_END); //扩展文件大小
    if(ret == -1)
    {
        perror("lseek");
        exit(-1);
    }
    //如果要想扩展文件,移动了指针还需要在后面写入空数据
    write(fd," ",1);

    printf("%d\n",ret);
    close(fd);
    return 0;
}

stat和lstat

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

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


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

int main()
{
    struct stat statbuf;
    int ret = stat("a.txt",&statbuf);
    if(ret == -1)
    {
        perror("stat");
        exit(-1);
    }
    printf("size:%ld\n",statbuf.st_size);
    return 0;
}

/*

创建软连接: ln -s a.txt b.txt
可以用lstat 获取他的信息,但是stat 获取不的是这个软连接对应的a.txt信息
*/
/*
模拟实现ls -l 指令
-rw-rw-r-- 1 zbz zbz 12 10月  3 19:15 a.txt
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <string.h>
int main(int argc, char *argv[])
{
    struct stat statbuf;
    if(argc < 2)
    {
        printf("%s filename\n",argv[0]);
        exit(-1);
    }
    int ret = stat(argv[1],&statbuf);
    if(ret == -1)
    {
        perror("stat");
        exit(-1);
    }
    //获取文件类型和文件权限
    char perms[11] = {0};   //用于保存文件类型和文件权限的字符串
    switch(statbuf.st_mode & __S_IFMT)
    {
        case __S_IFLNK:
            perms[0] = 'l';
            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] = '?';
            break;  
    }

    //判断文件访问权限
    //文件所有者
    perms[1] = (statbuf.st_mode & S_IRUSR) ? 'r':'-';
    perms[2] = (statbuf.st_mode & S_IWUSR) ? 'w':'-';
    perms[3] = (statbuf.st_mode & S_IXUSR) ? 'x':'-';

    //文件所在组
    perms[4] = (statbuf.st_mode & S_IRGRP) ? 'r':'-';
    perms[5] = (statbuf.st_mode & S_IWGRP) ? 'w':'-';
    perms[6] = (statbuf.st_mode & S_IXGRP) ? 'x':'-';
    
    //其他人
    perms[7] = (statbuf.st_mode & S_IROTH) ? 'r':'-';
    perms[8] = (statbuf.st_mode & S_IWOTH) ? 'w':'-';
    perms[9] = (statbuf.st_mode & S_IXOTH) ? 'x':'-';
    
    //获取硬连接数
    int linkNum = statbuf.st_nlink;

    //文件所有者
    char *fileUser = getpwuid(statbuf.st_uid)->pw_name;
    
    //文件所在组
    char * fileGrep = getgrgid(statbuf.st_gid)->gr_name;

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

    //获取修改时间
    char  *fileTime = ctime(&statbuf.st_mtime); //将时间转换为当前时间
    char mtime[512] = {0};
    strncpy(mtime,fileTime,strlen(fileTime)-1);
    
    char buf[1024];
    sprintf(buf,"%s %d %s %s %ld %s %s",perms,linkNum,fileUser,fileGrep,fileSize,mtime,argv[1]);

    printf("%s\n",buf);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值