linux下文件、文件夹相关操作(C语言)

简介: linux下文件、文件夹相关操作(C语言)

文章目录

linux下文件夹操作

相关API函数

opendir(3)

closedir(3)

readdir(3)

代码示例:

文件重定向的实现原理

相关API函数

dup(2)

dup2(2)

代码示例

文件锁

相关使用方式

代码示例

库函数和系统调用函数之间的关系

具体说明

代码示例

linux进程基础

相关API

代码示例


linux下文件夹操作

系统提供了一下库函数来操作文件夹:


相关API函数

opendir(3)

DIR *opendir(const char *name);
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个文件夹
参数:
name:指定了要打开的文件夹的名字
返回值:
NULL   错误   errno被设置
返回一个具体的地址


closedir(3)

int closedir(DIR *dirp);
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭一个文件夹
参数:
dirp:指定了要关闭的文件夹(opendir(3)的返回值)
返回值:
0   成功
-1   失败   errno被设置


readdir(3)

struct dirent *readdir(DIR *dirp);


#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读取文件夹的内容
参数:
dirp:指定文件夹。opendir(3)的返回值
返回值:
NULL   到达文件夹的末尾或者错误产生
如果errno被设置了,代表了错误产生
成功调用返回一个地址。
struct dirent{
  ino_t  d_ino; /* inode number */
        off_t  d_off;       /* offset to the next dirent */
        unsigned short d_reclen;    /* length of this record */
        unsigned char  d_type;      /* type of file; not supported
            by all file system types */
  char           d_name[256]; /* filename */
};


代码示例:

  • diros.c
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc,char *argv[]){
  struct dirent *p;
  //打开指定的文件夹
  DIR *dirp=opendir(argv[1]);
  if(dirp==NULL){
  perror("opendir");
  return 1;
  }
  printf("directory open success..\n");
  while((p=readdir(dirp))!=NULL){
  printf("%s\t%lu\n",\
    p->d_name,p->d_ino);
  }
  //关闭文件夹
  closedir(dirp);
  return 0;
}


  • 执行结果

20200205081631534.png

文件重定向的实现原理

文件重定向就是重新定位文件的流向。要完成文件重定向的功能,需要将文件描述符进行拷贝。


相关API函数

dup(2)

int dup(int oldfd);
#include <unistd.h>
int dup(int oldfd);
功能:复制一个文件描述符
参数:
oldfd:拷贝的样本
返回值:
-1  失败   errno被设置
新的文件描述符


dup2(2)

int dup2(int oldfd, int newfd);


功能:复制一个文件描述符
参数:
oldfd:拷贝的样本
newfd:指定新的文件描述符
返回值:
-1  失败   errno被设置
新的文件描述符


代码示例

  • direct.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void){
  int fd,s_fd;
  char msg[]="this is a test\n";
  fd=open("somefile",O_RDWR|O_CREAT,\
  0664);
  if(fd==-1){
  perror("open");
  return 1;
  }
  //复制标准输出文件描述符到s_fd
  s_fd=dup(STDOUT_FILENO);
  //将fd文件描述符复制到标准输出
  dup2(fd,STDOUT_FILENO);
  close(fd);
  //向标准输出文件描述符中输出字符串
  write(STDOUT_FILENO,msg,strlen(msg));
  dup2(s_fd,STDOUT_FILENO);
  write(STDOUT_FILENO,msg,strlen(msg));
  close(s_fd);
  return 0;
}


  • 执行结果

20200205082851891.png

文件锁

文件锁分为两种类型:


  • 强制锁
  • 建议锁

根据锁的互斥性又可以分为读锁(共享锁)、写锁(互斥锁)。


相关使用方式

使用fcntl完成文件锁的功能:


#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
功能:操作文件描述符
参数:
fd:指定要操作的文件描述符
cmd:对文件描述符的操作命令
F_GETLK 获取文件上的锁
F_SETLK  设置锁到文件。出现互斥锁的时候,非阻塞。
F_SETLKW 设置锁到文件,出现互斥锁的时候,阻塞。
返回值:
0   成功
-1 错误 errno被设置


struct flock {
       short l_type;    /* Type of lock: F_RDLCK,
                                   F_WRLCK, F_UNLCK */
       short l_whence;  /* How to interpret l_start:
                        SEEK_SET, SEEK_CUR, SEEK_END */
       off_t l_start;   /* Starting offset for lock */
       off_t l_len;     /* Number of bytes to lock */
       pid_t l_pid;     /* PID of process blocking our lock
                                   (F_GETLK only) */
};


代码示例

两个进程同时给一个文件添加读锁。


  • processA.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(void){
  int fd;
  //以读写方式打开文件
  fd=open("hello",O_RDWR);
  if(fd==-1){
  perror("open");
  return 1;
  }
  //定义锁变量
  struct flock lock;
  //初始化锁变量的字段内容
  lock.l_type=F_RDLCK;
  lock.l_whence=SEEK_SET;
  lock.l_start=0;
  lock.l_len=6;
  //给hello文件加读锁
  int f=fcntl(fd,F_SETLK,&lock);
  if(f==-1){
  perror("fcntl");
  return 2;
  }
  printf("添加读锁成功...\n");
  getchar();
  close(fd);
  return 0;
}


  • processB.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(void){
  int fd;
  //以读写方式打开文件
  fd=open("hello",O_RDWR);
  if(fd==-1){
  perror("open");
  return 1;
  }
  //定义锁变量
  struct flock lock;
  //初始化锁变量的字段内容
  lock.l_type=F_WRLCK;
  lock.l_whence=SEEK_SET;
  lock.l_start=0;
  lock.l_len=6;
  //给hello文件加读锁
  int f=fcntl(fd,F_SETLKW,&lock);
  if(f==-1){
  perror("fcntl");
  return 2;
  }
  printf("B添加读锁成功...\n");
  getchar();
  close(fd);
  return 0;
}


执行结果:

读锁结果

20200205084400137.png

修改B进程为写锁尝试:

发现B进程会在A进程使用期间阻塞等待。

20200205084635923.png

库函数和系统调用函数之间的关系

库函数:(缓冲文件)fopen、fclose、fputc、fgetc。

系统调用:(非缓冲文件)open、close、write、read。


具体说明

fopen(3)

分配结构体FILE的一块内存,在FILE类型中有一个成员变量_fileno,用于保存文件描述符。另外分配一块缓存,后边库函数对文件的读写操作是针对这块缓存的;调用open(2)打开相应的文件。


fgetc(3)

调用fgetc的时候,主要是针对缓存,从缓存中获取数据,如果缓存有数据,立即返回获取到的数据。如果缓存中没有数据,调用read(2),文件描述符有FILE类型的参数的_fileno传入。从系统中获取数据到缓存,然后fgetc(3)返回获取到的数据。


fputc(3)

调用fputc的时候,如果写缓存有空间,直接将字符写入到缓存;如果写缓存已经满,调用write(2)将写缓存中的内容写到文件,清楚缓存,然后将字符写入到写缓存。


fclose(3)

先清除缓存中的内容到文件,然后调用close(2)关闭文件描述符,然后,释放fopen(3)开辟的缓存空间。


代码示例

  • file.c
#include <stdio.h>
int main(void){
  FILE *fp;
  fp=fopen("hello","r");
  if(fp==NULL){
  perror("fopen");
  return 1;
  }
  printf("file open success...\n");
  fclose(fp);
  return 0;
}


  • 执行结果

20200205085438659.png

linux进程基础

程序和进程的区别:


  • 程序是静态的,存放在磁盘上,是指令的集合。
  • 进程是程序运行的实例,一个程序运行一次会产生一个进程。

每个进程都有自己的pid,每个进程都有自己的PCB。进程是资源分配的基本单位。

在linux操作系统下,进程直接的关系是斧子关系或者兄弟关系。

所有的用户级进程形成了一颗树,使用pstree可以查看这个树,init是这棵树的树根,也就是1号进程(用户进程的第一个进程)。

20200205085814226.png

相关API

如果创建一个新的进程?

使用系统调用fork(2)创建新进程。

pid_t fork(void);


#include <unistd.h>
pid_t fork(void);
功能:创建一个子进程
参数:
void
返回值:
-1错误,在父进程里返回,子进程不被创建。errno被设置。
成功:
在父进程里返回子进程的pid。
在子进程中0被返回。


代码示例

  • fork.c
#include <stdio.h>
#include <unistd.h>
int main(void){
  pid_t pid;
  //创建子进程
  pid=fork();
  if(pid ==-1){
  perror("fork");
  return 1;
  }
  if(pid==0){//子进程执行的代码
  printf("child\n");
  }else{//福进程执行的代码
  printf("parent\n");
  }
  return 0;
}


  • 执行结果

20200205090335542.png

相关文章
|
4天前
|
Linux 开发工具 Perl
在Linux中,有一个文件,如何删除包含“www“字样的字符?
在Linux中,如果你想删除一个文件中包含特定字样(如“www”)的所有字符或行,你可以使用多种文本处理工具来实现。以下是一些常见的方法:
22 5
|
5天前
|
安全 Linux 数据安全/隐私保护
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。本文介绍了使用 `ls -l` 和 `stat` 命令查找文件所有者的基本方法,以及通过文件路径、通配符和结合其他命令的高级技巧。还提供了实际案例分析和注意事项,帮助读者更好地掌握这一操作。
15 6
|
5天前
|
Linux
在 Linux 系统中,`find` 命令是一个强大的文件查找工具
在 Linux 系统中,`find` 命令是一个强大的文件查找工具。本文详细介绍了 `find` 命令的基本语法、常用选项和具体应用示例,帮助用户快速掌握如何根据文件名、类型、大小、修改时间等条件查找文件,并展示了如何结合逻辑运算符、正则表达式和排除特定目录等高级用法。
21 5
|
6天前
|
监控 Linux Perl
Linux 命令小技巧:显示文件指定行的内容
在 Linux 系统中,处理文本文件是一项常见任务。本文介绍了如何使用 head、tail、sed 和 awk 等命令快速显示文件中的指定行内容,帮助你高效处理文本文件。通过实际应用场景和案例分析,展示了这些命令在代码审查、日志分析和文本处理中的具体用途。同时,还提供了注意事项和技巧,帮助你更好地掌握这些命令。
17 4
|
11天前
|
网络协议 Linux
linux系统重要文件目录
本文介绍了Linux系统中的重要目录及其历史背景,包括根目录、/usr、/etc、/var/log和/proc等目录的结构和功能。其中,/etc目录下包含了许多关键配置文件,如网卡配置、DNS解析、主机名设置等。文章还详细解释了各目录和文件的作用,帮助读者更好地理解和管理Linux系统。
33 2
|
10天前
|
缓存 监控 Linux
|
13天前
|
Linux Shell 数据库
文件查找是Linux用户日常工作的重要技能介绍了几种不常见的文件查找方法
文件查找是Linux用户日常工作的重要技能。本文介绍了几种不常见的文件查找方法,包括使用`find`和`column`组合、`locate`和`mlocate`快速查找、编写Shell脚本、使用现代工具`fd`、结合`grep`搜索文件内容,以及图形界面工具如`Gnome Search Tool`和`Albert`。这些方法能显著提升文件查找的效率和准确性。
34 2
|
6月前
|
Linux
百度搜索:蓝易云【Linux中如何对文件进行压缩和解压缩?】
这些是在Linux中进行文件压缩和解压缩的常见方法。根据您的需求和具体情况,可能会使用其他压缩工具和选项。您可以通过查阅相应命令的帮助文档来获取更多详细信息。
87 1
|
6月前
|
NoSQL Java Linux
Linux常用命令(文件目录操作、拷贝移动、打包压缩、文本编辑、查找)
Linux常用命令(文件目录操作、拷贝移动、打包压缩、文本编辑、查找)
|
6月前
|
算法 Java Linux
Linux下文件增删改查定位压缩操作与权限所属用户
Linux下文件增删改查定位压缩操作与权限所属用户
71 0