Linux系统函数

虚拟地址空间:

linux没运行一个程序(进程)操作系统都会分配一个0~4G的地址空间(虚拟地址空间)

文件描述符:通过文件描述符可以找到磁盘文件

一个进程有一个文件描述符表:1024

  • 前三个被占用,被标准输入,标准输出,标准错误占用

  1. open函数的使用

函数原型:

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

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

参数:

  • flags

  • 必选项:O_RDONLY,O_WRONLY,O_RDWR

  • 可选项:

  • 创建文件:O_CREAT

  • 创建文件时检测文件是否存在:O_EXCL

  • 如果文件存在,返回-1

  • 必须与O_CREAT一起使用

  • 追加文件: O_APPEND

  • 文件截断:O_TRUNC

  • 设置非阻塞:O_NONBLOCK

  • mode:是一个八进制数

代码实例

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

int main()
{
        //打开一个文件 hello
        int fd = open("hello", O_RDWR|O_CREAT, 0777);//第一个是文件名,第二个参数是指定的操作,第三个参数是给定的权限
        if(fd == -1)
        {
                printf("打开失败\n");
        }
        close(fd);//关闭文件描述符
        return 0;
}
  1. read_write函数

  1. read函数:包含在头文件 <unistd.h>

函数原型:ssize_t read(int fd, void *buf, size_t count);

  • 参数:

  • fd:open返回值

  • buf:缓冲区

  • count:缓冲区能存储的最大字节数

  • 返回值:

  • -1:表示读取失败

  • 成功:

  • >0:表示读取的字节数

  • =0:表示读完了

b. write函数:包含在头文件 <unistd.h>

函数原型:ssize_t write(int fd, const void *buf, size_t count);

参数:

  • fd:open的返回值

  • buf:要写到文件的数据

  • count:buf的有效字节数

  • 返回值:

  • -1:表示写入失败

  • >0:写入到文件的字节数

代码实例:

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


int main()
{
        int fd = open("text.txt", O_RDONLY);
        if(fd == -1)
        {
                printf("打开失败\n");
        }
        int fd2 = open("text2.txt", O_WRONLY|O_CREAT, 0777);
        char arr[20] = {0};
        int len = read(fd, arr, 20);
        while(len > 0)
        {
                int ret = write(fd2, arr, strlen(arr));
                len = read(fd, arr, sizeof(arr));
        }

        close(fd2);
        close(fd);
        return 0;
}

  1. perror函数:包含的头文件 <errno.h>

函数原型:void perror(const char *s);

作用:输出错误信息

参数s:指定错误信息的标识

  1. lseek 函数:包含在头文件 <sys/types.h> <unistd.h>

函数原型:off_t lseek(int fd, off_t offset, int whence);

参数 whence选项:

  • SEEK_SET

  • SEEK_CUR

  • SEEK_END

使用:

  1. 文件指针移动到头部

lseek(fd, 0, SEEK_SET);

  1. 获取文件指针当前的位置

int len = lseek(fd, 0, SEEk_CUR);

  1. 获取文件长度:

int lne = lseek(fd, 0, SEEK_END);

  • 文件扩展

文件原大小100k 扩展为 1000k

lseek(fd, 1000, SEEK_END);

最后做一次写操作

write(fd, "a", 1);

要实现文件扩展必须执行上面两部

文件扩展代码

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

int main(int argc, const char* argv[])
{
        int fd = open("english.txt", O_RDWR);
        printf("fd = %d\n", fd);
        if(fd == -1)
        {
                perror("open");
                return -1;
        }
        //文件扩展
        int len = lseek(fd, 1000, SEEK_END);//第二个参数表示文件指针移动的位数, 第三个参数表示从末尾开始移动
        printf("len = %d\n", len);
        write(fd, "a", 1);
        close(fd);

        return 0;

}
  1. 阻塞和非阻塞

取决于文件的属性:

普通文件:默认是非阻塞

终端设备:/dev/tty,默认阻塞

  1. stat和lstat函数:包含的头文件 <sys/types.h> <sys/stat.h> <unistd.h>

函数原型: int stat(const char *pathname, struct stat *statbuf);

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

两个函数的区别:

  • lstat:读取的链接文件本身的属性

  • stat:读取的是链接文件指向的文件的数学

参数pathname:文件路径

参数statbuf:是一个stat结构体对象

stat结构体:

 struct stat {
               dev_t     st_dev;         //文件的设备编号
               ino_t     st_ino;         //节点
               mode_t    st_mode;        //文件的类型和存取的权限
               nlink_t   st_nlink;       //连到该文件的硬连接数目,刚建立的文件值为1
               uid_t     st_uid;         //用户ID
               gid_t     st_gid;         //组ID
               dev_t     st_rdev;        //(设备类型)若此文件为设备文件,则为其设备编号
               off_t     st_size;        //文件字节数(文件大小)
               blksize_t st_blksize;     //块大小(文件系统的I/O缓冲区大小)
               blkcnt_t  st_blocks;      //块数
               struct timespec st_atim;  //最后一次访问时间
               struct timespec st_mtim;  //最后一次修改时间
               struct timespec st_ctim;  //最后一次改变时间(指属性)
};

获取文件各种属性:

文件用16位进制数表示所有的权限:

  • 0-2位:表示其他人的权限

  • 3-5位:表示所属组织的权限

  • 6-8位:表示文件所有者权限

  • 12-15位:表示文件所有者权限

  • 掩码 S_IFMT:0170000 是八进制数,过滤 st_mode 中出文本类型以外的信息

例子:(st_mode & S_IFMT) == S_IFREG

使用代码实例:

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

int main()
{
        struct stat st;
        int ret = stat("english.txt", &st);
        if(ret == -1)
        {
                perror("stat error");
                exit(1);
        }
        //输出文件大小
        printf("file size = %d\n", (int)st.st_size);
        //文件类型判断--判断是否是普通文件
        if((st.st_mode & S_IFMT) == S_IFREG)//S_IFMT 是一个掩码,获取到的文件与上该掩码可以得到一个对应类型的二进制数
        {
                printf("该文件是普通文件\n");
        }
        //所有者对文件的操作权限
        if(st.st_mode & S_IRUSR)
        {
                printf("        r\n");
        }
        if(st.st_mode & S_IWUSR)
        {
                printf("        w\n");
        }
        if(st.st_mode & S_IXUSR)
        {
                printf("        X\n");
        }
        return 0;
}
  1. access函数:包含在头文件 <unistd.h>

作用:检查文件属性

函数原型:int access(const char *pathname, int mode);

参数 pathname:文件的路径

参数 mode:检查的属性

可选项:R_OK,W_OK以及X_OK

代码实例

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main(int argc, char* argv[])
{
        if(argc < 2)
        {
                printf("a.out fileman\n");
                exit(1);
        }
        //检测当前文件是否有写权限
        int ret = access(argv[1], W_OK);
        if(ret == -1)
        {
                perror("access");
                exit(1);
        }
        printf("you can write this file.\n");
        return 0;
}
  1. chmod和 chown函数

  1. chmod函数的作用:修改文件权限

  1. 函数原型:int chmod(const char *pathname, mode_t mode); 包含在头文件 <sys/stat.h>

  • 参数pathname:文件路径

  • 参数mode:文件权限,是一个八进制数

  1. chown函数的作用:修改文件所有者和所属组

  1. 函数原型:int chown(const char *pathname, uid_t owner, gid_t group); 包含在头文件 <unistd.h>

  • 参数pathname:文件路径

  • 参数owner:整形值,用户ID

  • 参数group:整型值,组ID

  1. opendir和readdir函数:包含在头文件 <dirent.h>

  1. opendir函数的作用:打开一个目录

  1. opendir函数原型:DIR *opendir(const char *name);

  • 参数 name:目录名

  • 返回值:指向目录的指针

  1. readir函数的作用:读目录

  1. readdir函数的原型:struct dirent *readdir(DIR *dirp);

  • 参数dirp:opendir的返回值

  • 返回值:目录项结构

dirent结构体

struct dirent {
               ino_t          d_ino;       //此目录进入点的inode
               off_t          d_off;       //目录文件开头至此目录进入点的位移
               unsigned short d_reclen;    //d_name 的长度,不包含NULL 字符
               unsigned char  d_type;      //d_name所指的文件类型
               char           d_name[256]; // 文件名
           };

文件类型:

  • DT_BLK-块设备

  • DT_CPR-字符设备

  • DT_DIR-目录

  • DT_LNK-软连接

  • DT_FIFO-爸道

  • DT_REG-普通文件

  • DT_SOCK-套接字

  • DT_UNKNOWN-未知

closedir函数:关闭目录

函数原型:int closedir(DIR *dirp);

程序实例

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

//定义函数读指定目录中文件的个数
int getfile(const char* root)
{
        int total = 0;
        DIR* dir = NULL;
        dir = opendir(root);
        if(dir == NULL)
        {
                perror("opendir");
                exit(0);
        }
        struct dirent* ptr;
        while((ptr = readdir(dir)) != NULL)
        {
                //不处理 . 和 .. 目录
                if(strcmp(".", ptr->d_name) == 0 || strcmp("..", ptr->d_name) == 0)
                {
                        continue;
                }
                //判断是否是普通文件
                if(ptr->d_type == DT_REG)
                {
                        total++;
                }
                //判断是否是目录
                if(ptr->d_type == DT_DIR)
                {
                        //求出子目录
                        char path[1024] = {0};
                        sprintf(path, "%s/%s", root, ptr->d_name);//拼接子目录
                        total += getfile(path);
                }
        }

        //关闭目录
        closedir(dir);

        return total;
}

int main(int argc, const char* argv[])
{
        if(argc < 2)
        {
                printf("./a.out path\n");
                exit(1);
        }
        int total = getfile(argv[1]);
        printf("%s 目录下的普通文件个数:%d\n", argv[1], total);

        return 0;
}

  1. dup和dup2函数:包含的头文件 <unistd.h>

  • dup函数的作用:复制文件描述符

  • dup函数的函数原型:int dup(int oldfd);

  • 参数oldfd:要复制的文件描述符

  • 返回值:新的文件描述符

  • dup调用成功:会有两个文件描述符指向同一个文件

  • 返回值:取最小的且没被占用的文件描述

dup2函数的作用:文件描述符重定向

dup2函数的原型:int dup2 (int oldfd, int newfd);

  • 参数oldfd:如果指向 hello

  • 参数newfd:如果指向 world

  • 调用dup2函数会把newfd改为指向oldfd指向的文件,也就是newfd也会指向hello的文件->文件描述重定向

  • newfd没有被占用的情况下,newfd指向oldfd指向的文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱笑的蛐蛐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值