前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux内核编程--常见的文件操作

Linux内核编程--常见的文件操作

作者头像
Coder-ZZ
发布2022-05-09 21:41:58
2K0
发布2022-05-09 21:41:58
举报
文章被收录于专栏:C/C++进阶专栏C/C++进阶专栏

1.文件描述符复制函数--dup/dup2/fcntl

代码语言:javascript
复制
#include <unistd.h>
int dup(int fd); /*复制一个现有文件的描述符*/
int dup2(int fd, int fd2); /*把一个文件的旧描述符复制到一个新描述符上*/

函数执行后,返回的新文件描述符与原有的旧文件描述符共用同一个文件表项,但是文件描述符标志将被清除,进程调用exec时文件描述符将不会被关闭。

dup()返回的新文件描述符一定是当前可用文件描述符中的最小值。

dup2()可以用fd2指定新描述符的值。如果fd2已经打开,则先将其关闭。若fd==fd2, 则dup2返回fd2,而不关闭它。

代码样例:

Demo1: 重定向进程的stdin、stdout以及stderr到filename文件

代码语言:javascript
复制
int fd = open(filename, O_WRONLY, 0666);
dup2(fd, STDOUT_FILENO); 
dup2(fd, STDERR_FILENO);
dup2(fd, STDERR_FILENO);

Demo2:

代码语言:javascript
复制
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>

int main(){
    int fd_old = open("test.txt", O_RDWR | O_CREAT, 0666);
    int fd_new = dup(fd_old);
    int fd_new_2 = dup2(fd_old, 6);

    if((fd_new == -1) || (fd_new_2 == -1)){   
        perror("dup or dup2 failed");
        return -1;
    }

    printf("fd_old : %d, fd_new : %d \n, fd_new_2 : %d \n", fd_old, fd_new, fd_new_2);
    close(fd_old);

    char *str = "hello world!";
    int ret = write(fd_new, str, strlen(str));
    if(ret == -1){
        perror("write failed");
        return -2;
    }

    close(fd_new);
    return 0;
}

运行结果:

代码语言:javascript
复制
fd_old : 3, fd_new : 4, fd_new_2 : 6

fcntl函数:根据传来的cmd参数来修改已经打开文件的属性

dup(fd)等效于fcntl(fd, F_DUPFD, 0),dup2(fd, fd2)等效于“close(fd2); fcntl(fd, F_DUPFD, fd2)"

代码语言:javascript
复制
#include <fcntl.h>
int fcntl(int fd, int cmd, ... );
--fd表示需要操作的文件描述符,cmd表示对文件描述符进行如何操作
--常用的cmd:
(1) 复制一个已有的描述符(cmd = F_DUPFD/F_DUPFD_CLOEXEC)
(2) 获取/设置文件描述符标志(cmd = F_GETFD/SETFD)
(3) 获取/设置文件状态标志(cmd = F_GETFL/F_SETFL)
(4) 获取/设置异步I/O所有权(cmd = F_GETOWN/F_SETOWN)
(5) 获取/设置记录锁(cmd = F_GETLK/F_SETLK/F_SETLKW)

代码样例:

代码语言:javascript
复制
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
  int flags;
  int append_flag;
  int nonblock_flag;
  int access_mode;
  int fd; /* File Descriptor */
  char *text1 = "abcdefghij";
  char *text2 = "0123456789";
  char read_buffer[25];

  memset(read_buffer, '\0', 25);

  /* create a new file */
  fd = creat("test.txt",S_IRWXU);
  write(fd, text1, 10);
  close(fd);

  /* open the file with read/write access */
  fd = open("test.txt", O_RDWR);
  read(fd, read_buffer, 24);
  printf("first read is \'%s\'\n",read_buffer);

  /* reset file pointer to the beginning of the file */
  lseek(fd, 0, SEEK_SET);
  /* set append flag to prevent overwriting existing text */
  fcntl(fd, F_SETFL, O_APPEND);
  write(fd, text2, 10);
  lseek(fd, 0, SEEK_SET);
  read(fd, read_buffer, 24);
  printf("second read is \'%s\'\n",read_buffer);

  close(fd);
  unlink("test.txt");

  return 0;
}

运行结果:

代码语言:javascript
复制
first read is 'abcdefghij'
second read is 'abcdefghij0123456789'

2.获得文件信息的函数 stat/fstat/lstat

代码语言:javascript
复制
#include <sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
int lstat(const char *restrict pathname, struct stat *restrict buf);
int fstat(int fd, struct stat *buf);

buf是一个指向stat结构体的指针:

代码语言:javascript
复制
struct stat {
     dev_t     st_dev;         /* ID of device containing file */
     dev_t     st_rdev;        /* Device ID (if special file) */
     ino_t     st_ino;         /* Inode number */
     mode_t    st_mode;        /* File type and mode */
     nlink_t   st_nlink;       /* Number of hard links */
     uid_t     st_uid;         /* User ID of owner */
     gid_t     st_gid;         /* Group ID of owner */               
     off_t     st_size;        /* Total size, in bytes */
     blksize_t st_blksize;     /* Block size for filesystem I/O */
     blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */
     struct timespec st_atim;  /* Time of last access */
     struct timespec st_mtim;  /* Time of last modification */
     struct timespec st_ctim;  /* Time of last status change */
};

stat结构体中的 st_mode:

stat函数和lstat函数的区别:假设有一个文件快捷方式(windows系统),lstat只分析快捷方式的信息,而stat分析的是快捷方式对应的原文件的信息。linux系统中的”快捷方式“被称为软链接。

代码样例:

代码语言:javascript
复制
#include <sys/stat.h>
#include <unistd.h>
main()
{
    struct stat buf;
    stat("/etc/yum", &buf);
    printf("/etc/yum file_size = %d \n", buf.st_size);
    printf("/etc/yum file_mode = %s \n", buf.st_mode);
    printf("/etc/yum Device_ID = %d \n", buf.st_dev);
}

运行结果:

代码语言:javascript
复制
/etc/yum file_size = 4096
/etc/yum file_mode = 16877
/etc/yum Device_ID = 64769

Linux中的stat命令:

用法:

代码语言:javascript
复制
stat [OPTION]... FILE...

常见参数:

代码语言:javascript
复制
  -L, --dereference     
  -f, --file-system     display file system status instead of file status
  -c  --format=FORMAT   use the specified FORMAT instead of the default;
                          output a newline after each use of FORMAT
      --printf=FORMAT   like --format, but interpret backslash escapes,
                          and do not output a mandatory trailing newline;
                          if you want a newline, include \n in FORMAT
  -t, --terse    print the information in terse form

命令执行样例:

3.权限屏蔽字函数umask

在Linux操作系统创建的文件总是有对应的默认权限,这个权限可以由umask进行设置,umask与chmod的效果刚好相反,umask设置的是权限位的“补码”。有了umask对默认权限的设置,当创建一个文件后,新文件的默认权限就是最大权限减去 umask 指定的权限

文件权限在Linux中的表示:

代码语言:javascript
复制
[root@VM-4-13-centos cpp_learning]# ls -l hello.txt
-rw-r--r-- 1 root root 12 Apr 13 00:07 hello.txt

umask函数一般用来为进程设置文件模式创建屏蔽字,并返回之前的值。

当编写创建新文件的程序时,如果我们想确保指定的访问权限位已经激活,那么必须在进程运行时修改umask值。

例如,如果我们想确保任何用户都能读文件,应该把umask设置为0。

代码语言:javascript
复制
#include <sys/stat.h>
mode_t umask(mode_t, cmask);

用户可以设置cmask值以控制他们所创建文件的默认权限。

cmask常见取值:

代码语言:javascript
复制
S_IRUSR  当前用户可读
S_IWUSR  当前用户可写
S_IXUSR  当前用户可执行
S_IRGRP  用户组可读
S_IWGRP  用户组可写
S_IXGRP  用户组可执行
S_IROTH  其他用户可读
S_IWOTH  其他用户可写
S_IXOTH  其他用户可执行

代码样例:

代码语言:javascript
复制
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <stdio.h>

main() {
  int fd;
  mode_t oldmask;
  printf("Your old umask is %i\n",oldmask=umask(S_IRWXG));
  if ((fd = creat("test.txt", S_IRWXU|S_IRWXG)) < 0)
    perror("creat() error");
  else {
    system("ls -l test.txt");
    close(fd);
    unlink("test.txt");
  }
  umask(oldmask);
}

运行结果:

代码语言:javascript
复制
Your old umask is 36
-rwx------ 1 root root 0 Apr 13 10:24 test.txt

Linux umask指令

代码语言:javascript
复制
umask [-p] [-S] [mode]

命令执行样例:

~~The End~~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员与背包客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档