Linux下文件/目录操作的相关函数

news2024/11/17 0:54:41

1.文件系统

把一个磁盘分成一个或多个分区。每个分区可用包含一个文件系统

文件系统是,一组规则,规定对文件的存储及读取的一般方法。文件系统在磁盘格式化过程中指定。

常见的文件系统有:fat32 ntfs exfat ext2 、ext3 、ext4

inode是固定长度的记录项,包含有关文件的大部分信息

inode

其本质为结构体,存储文件的属性信息。如:权限、类型、大小、时间、用户、盘块位置……也叫作文件属性管理结构,大多数的inode都存储在磁盘上。

少量常用、近期使用的inode会被缓存到内存中。

  • 每个inode中有一个链接数,其值为指向该inode的目录项数(上图中有两个目录项指向同一个inode)。只有当链接数减为0时,才删除该文件。链接数包含在stat结构的st_nlink成员中(POSIX.1常量LINK_MAX指定了一个文件链接数的最大值)。这种链接类型称为硬链接
  • 另外一种链接类型称为符号链接。符号链接文件的实际内容(在数据块中)包含了该符号链接所指向的文件的名字
  • inode包含了文件有关的所有信息:文件类型、文件访问权限位、文件长度和指向文件数据块的指针等。stat结构中的大多数信息都取自inode。只有2项重要数据存放在目录项中:文件名和inode号
  • 因为目录项中的inode编号指向同一文件系统中的相应inode,一个目录项不能指向另一个文件系统的inode
  • 在不更换文件系统的情况下为一个文件重命名时,该文件的实际内容并未移动,只需构造一个指向现有inode的新目录项,并删除老的目录项。链接数不会改变

下图为在一个目录下创建一个目录testdir,注意testdir所在目录,以及新建目录testdir的inode链接数:

dentry

目录项,其本质依然是结构体,重要成员变量有两个 {文件名,inode,...},而文件内容(data)保存在磁盘盘块中。

也就是上一点inode图中包含inode结点编号和文件名的那一块

不同的文件有相同的inode号实现存储在同一块分区内,也就是硬链接

硬链接其中就要求到要处在同一块分区内,并且针对的是文件

2.文件操作

stat函数

使用stat函数最多的地方可能就是ls -l命令获得有关一个文件的所有信息

获取文件属性,存在buf中(从inode结构体中获取)
int stat(const char *path, struct stat *buf); 
        成返回0;失败返回-1 设置errno为恰当值。
        参数1:文件路径
        参数2:inode结构体指针,存放文件属性 (传出参数)

文件属性将通过传出参数返回给调用者。
练习:使用stat函数查看文件属性
【stat.c】
#include<syss/types.h>
#include<sys/stat.h>
#include<unistd.h>
文件信息结构用一个结构体stat表示,实际定义可能随具体实现有所不同,但基本形式是:
struct stat{
    mode_t              st_mode;    /*文件模式字,包含有文件类型、ID和读写权限位信息*/
    ino_t               st_ino;     /* inode号 */
    dev_t               st_dev;     /* 设备号(文件系统) */
    dev_t               st_rdev;    /* 特殊文件的设备号 */
    nlink_t             st_nlink;   /* 链接数 */
    uid_t               st_uid;     /* 所有者的用户ID */
    gid_t               st_gid;     /* 组所有者的ID */
    off_t               st_size;    /* 字节大小,用于一般文件 */
    struct timespec     st_atime;   /* 最后一次访问时间 */
    struct timespec     st_mtime;   /* 最后一次修改时间 */
    struct timespec     st_ctime;   /* 最后一个文件状态改变的时间 */
    blksize_t           st_blksize; /* 磁盘块(block)大小 */
    blkcnt_t            st_blocks;  /* 分配的磁盘块(block)数量 */
};

stat结构体中的st_size属性:

stat结构体中的st_mode属性:

st_mode属性:

  • 普通(一般)文件
  • 目录文件
  • 字符特殊文件:这种类型的文件提供对设备不带缓冲的访问,每次访问长度可变(系统中的所有设备要么是字符特殊文件,要么是块特殊文件)
  • 块特殊文件:这种类型的文件提供对设备(如磁盘)带缓冲的访问,每次访问以固定长度为单位进行
  • FIFO:这种类型的文件用于进程间通信,有时也称为命名管道
  • 符号链接:这种类型的文件指向另一个文件
  • 套接字:这种类型的文件用于进程间的网络通信

提供了一些宏定义供于查看文件是否为目录等

stat函数在查看链接的时候会穿透,比如给一个文件起软链接后,去查看这个软链接对应的链接名,会把它当作一个文件,而不是显示它是一个链接

lstat函数

类似于stat。但是当pathname为一个符号链接时,返回符号链接(而不是由该符号链接引用的文件)的有关信息,存在buf中

【get_file_type.c】
int lstat(const char *path, struct stat *buf); 
成返回0;失败返回-1 设置errno为恰当值。

文件类型判断方法:st_mode 取高4位。 但应使用宏函数:           
       S_ISREG(m)  is it a regular file?
       S_ISDIR(m)  directory?
       S_ISCHR(m)  character device?
       S_ISBLK(m)  block device?
       S_ISFIFO(m) FIFO (named pipe)?
       S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)
       S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)
穿透符号链接:stat:会;lstat:不会

不穿透符号链接其实在其他方面也见到过:

给一个文件 f.c 起符号链接 f.link 后,用cat f.link 或 vim f.link 都能对 f.c 进行操作(穿透符号链接),但是如果用 ls -l f.link 会发现不穿透符号链接,会把 f.c 的文件信息优先显示出来而不是显示 f.link 文件的信息

系统和命令其实就是实现与被实现的关系

另外一种方式去获取文件的类型:(了解)

用按位与的方式,而不是直接采用宏定义去判断

IFMT实际上就是16位的位图掩码,来表示文件的权限类型

特殊权限位置

黏住位

即S_ISVTX

  • 在UNIX尚未使用请求分页式技术的早期版本中,S_ISVTX位被称为粘着位
  • 后来的UNIX版本称它为保存正文位

用途

  • 以前,如果一个可执行文件设置了该位,当程序第一次被执行,在其终止时,程序正文部分的一个副本仍被保存在交换区。这使得下次执行该程序时能较快地将其装载入内存(原因是:通常的UNIX文件系统中,文件的各数据块很可能是随机存放的,相比较而言,交换区是被作为一个连续文件来处理的)
  • 现在,系统扩展了粘着位的使用范围,Single UNIX Specification允许针对目录设置粘着位。如果对一个目录设置了该位,只有满足下列2个情况,才能删除或重命名该目录下的文件:

对该目录具有写权限

  1. 满足下列条件之一:
  2. 拥有此文件
  • 拥有此目录
  • 是超级用户

目录/tmp和/var/tmp就是设置粘着位的典型候选者

setUID位

进程有两个ID:

  • EID(有效用户ID),表示进程履行哪个用户的权限。
  • UID(实际用户ID),表示进程实际属于哪个用户。

多数情况下,EID和UID相同。但是,当文件的setID被设置后两个ID则有可能不一样。

例如:当进程执行一个root用户的文件,若该文件的setID位被设置为1, 那么执行该文件时,进程的UID不变。EID变为root,表示进程开始履行root用户权限。

access函数

测试指定文件是否存在/拥有某种权限。
int access(const char *pathname,  int mode); 
    返回值:成功/具备该权限:0;失败/不具备 -1 设置errno为相应值。
    参数2:R_OK、W_OK、X_OK
通常使用access函数来测试某个文件是否存在。F_OK

chmod函数

 修改文件的访问权限
 int chmod(const char *path, mode_t mode);
     成功:0;失败:-1设置errno为相应值
 int fchmod(int fd, mode_t mode);

truncate函数

截断文件长度成指定长度。常用来拓展文件大小,代替lseek。
       int truncate(const char *path, off_t length);
           成功:0;失败:-1设置errno为相应值
       int ftruncate(int fd, off_t length);

link函数

思考,为什么目录项要游离于inode之外,画蛇添足般的将文件名单独存储呢??这样的存储方式有什么样的好处呢?

其目的是为了实现文件共享。Linux允许多个目录项共享一个inode,即共享盘块(data)。不同文件名,在人类眼中将它理解成两个文件,但是在内核眼里是同一个文件。

link函数,可以为已经存在的文件创建目录项dentry(硬链接)。
int link(const char *oldpath,  const char *newpath);
    成功:0;失败:-1设置errno为相应值
    注意:由于两个参数可以使用“相对/绝对路径+文件名”的方式来指定,所以易出错。
如:link("../abc/a.c", "../ioc/b.c")
    若a.c,b.c都对, 但abc,ioc目录不存在也会失败。

mv命令既是修改了目录项,而并不修改文件本身,可以通过link和unlink来实现mv

硬链接实际上就是创建了一个目录项,与原文件具有相同的inode节点号,指向了同一盘块位置

unlink函数

 删除一个文件的目录项;
int unlink(const char *pathname);
     成功:0;失败:-1设置errno为相应值
练习:编程实现mv命令的改名操作
【imp_mv.c】
注意Linux下删除文件的机制:不断将st_nlink -1,直至减到0为止。无目录项对应的文件,将会被操作系统择机释放。(具体时间由系统内部调度算法决定)

因此,我们删除文件,从某种意义上说,只是让文件具备了被释放的条件。
unlink函数的特征:清除文件时,如果文件的硬链接数到0了,没有dentry对应,但该文件仍不会马上被释放。要等到所有打开该文件的进程关闭该文件,系统才会挑时间将该文件释放掉。
【unlink_exe.c】

实现mv:

比如想实现像mv将a.c改名为b.c:mv ./a.c ./b.c

link("./a.c", "./b.c");

unlink("./a.c");

unlink后目录项被释放掉,此时打开另一个终端去cat查看下该文件是查找不到的,但是unlink后的write是仍可以写的,只不过写入到stat相关的缓冲区当中,因此不会将if语句中的内容打印出来,此时进程还在继续当中,temp.txt文件还没被释放掉

隐形回收

当进程结束运行时,所有该进程打开的文件会被关闭,申请的内存空间会被释放。系统的这一特性称之为隐式回收系统资源。

symlink函数

创建一个符号链接
int symlink(const char *oldpath, const char *newpath);
成功:0;失败:-1设置errno为相应值

readlink函数

读取符号链接文件本身内容,得到链接所指向的文件名。
ssize_t readlink(const char *path, char *buf, size_t bufsiz);
成功:返回实际读到的字节数;失败:-1设置errno为相应值。
在终端窗口中也适用:
ln -s test.c test.soft
cat test.soft
>>>这是一个目录
readlink test.soft
>>>(显示软链接所指向的目录位置)

rename函数

重命名一个文件。
 int rename(const char *oldpath, const char *newpath); 
 成功:0;失败:-1设置errno为相应值

3.目录操作

工作目录:“./”代表当前目录,指的是进程当前的工作目录,默认是进程所执行的程序所在的目录位置。

目录操作的函数是在man的第三卷,是库函数

getcwd函数

获取进程当前工作目录(卷3,标库函数)
char *getcwd(char *buf, size_t size);
    成功:buf中保存当前进程工作目录位置。失败返回NULL。

chdir函数

每个进程都有一个当前工作目录,此目录是搜索所有相对路径名的起点(不以斜线开始的路径名为相对路径名)

用户登录到UNIX系统时,其当前工作目录通常是口令文件(/etc/passwd)中该用户登录项的第6个字段——用户的起始目录

  • 当前工作目录是进程的一个属性(所以如果调用chdir修改当前目录,只影响调用函数的进程本身)
  • 起始目录则是登录名的一个属性
改变当前进程的工作目录
int chdir(const char *path); 
    成功:0;失败:-1设置errno为相应值

文件、目录权限

目录文件也是“文件”,其文件内容是该目录下所有子文件的目录项dentry,可以尝试vim打开一个目录。

R

W

X

文件

文件的内容可以被查看

cat、more、less...

内容可以被修改

vi、>...

可以运行产生一个进程

./文件名

目录

目录可以被浏览

ls、tree...

创建、删除、修改文件

mv、touch、mkdir...

可以被打开、进入

cd

目录设置黏住位:若有w权限,创建不变,删除、修改只能由root、目录所有者、文件所有者操作。

查看目录的详情:

ls -ld test.dir/

opendir函数

根据传入的目录名打开一个目录 (库函数)
DIR * 类似于 FILE *
DIR *opendir(const char *name);  
# 成功返回指向该目录结构体指针,失败返回NULL
# 参数支持相对路径、绝对路径两种方式:例如:打开当前目录:① getcwd() , opendir() ② opendir(".");

closedir函数

关闭打开的目录
int closedir(DIR *dirp);
# 成功:0;失败:-1设置errno为相应值

readdir函数

读取目录(库函数)
struct dirent *readdir(DIR *dirp);  
# 成功返回目录项结构体指针;失败返回NULL设置errno为相应值
# 需注意返回值,读取数据结束时也返回NULL值,所以应借助errno进一步加以区分。
struct 结构体:
           struct dirent {
               ino_t          d_ino;      inode编号
               off_t          d_off;       
               unsigned short  d_reclen;    文件名有效长度
               unsigned char   d_type;     类型(vim打开看到的类似@*/等)
               char          d_name[256];文件名
           };

实现ls不打印隐藏文件。每5个文件换一个行显示。【imp_ls2.c】

. 和 .. 是隐藏文件

rewinddir函数

回卷目录读写位置至起始。
void rewinddir(DIR *dirp);
返回值:无

telldir/seekdir函数

获取目录读写位置
long telldir(DIR *dirp); 
成功:与dirp相关的目录当前读写位置。失败-1,设置errno

修改目录读写位置
void seekdir(DIR *dirp, long loc); 
返回值:无
参数loc一般由telldir函数的返回值来决定。

4.递归遍历目录

查询指定目录,递归列出目录中文件,同时显示文件大小

ls -R
ls-R.c  --> 通过命令行在运行的时候直接传入要递归的目录名
1.判断命令行参数,获取用户要查询的目录。
    如果用户没有输入目录名(ls -R ==> ls -R .),进行转化, argc == 1 --> ./
2.判断用户指定的是否是目录。stat S_ISDIR()   --> 封装函数 isFile
3.读目录
    opendir(dir)
    while(reddir(dir)){
        普通文件:直接打印
        目录:
            拼接目录访问绝对路径。sprintf(path,"%s/%s",dir,d_name)
                # 递归调用自己传入的路径应当是绝对路径比较稳妥
            递归调用自己。 -->  opendir(path)
         readdir closedir                                     
    }
#include<unistd.h>
#include<sys/stat.h>
#include<dirent.h>
#include<stdio.h>
#include<stdblib.h>
#include<string.h>
#define PATH_LEN 256

void fetchdir(const char *dir, void (*fcn)(char *)) //该函数被调用则表示输入的是目录
{
    char name[PATH_LEN];
    struct dirent *sdp;
    DIR *dp;
    if((dp = opendir(dir)) == NULL){
        fprintf(stderr, "fetchdir:can't open %s\n",dir);
        return;    
    }
    while((sdp = readdir(dp)) != NULL){
        if(strcmp(sdp->name,".") == 0 || strcmp(sdp->name,"..") == 0){  // 防止出现死循环
            continue;
        }
        if(strlen(dir) + strlen(sdp->d_name) + 2 > sizeof(name)){
            //要求文件名+路径长度不大于256 
            fprintf(stderr, "fetchdir: name %s %s too long\n",dir, sdp_d_name);                   
        }else{
            sprintf(name, "%s/%s",dir,sdp->d_name);  //进行拼接成绝对路径
            (*fcn)(name); //回调函数调用进入下一论判断        
        }    
    }
}

void ifFile(char *name)
{
    struct stat sbuf;
    if(stat(name, &sbuf) == -1)  //文件名无效
    {
        fprintf(stderr, "isfile:can't access %s\n", name);
        exit(-1);
    }
    if((sbuf.st_mode & S_IFMT) == S_IFDIR) // 判定是否为目录
    {
         fetchdir(name,isfile); //回调函数       
    }
    printf("%10ld  %s\n", sbuf.st_size,name);  //普通文件,直接打印文件名
}

int main(int argc, int *agrv[])
{
    if(argc == 1)
        isFile(".");
    else
        while(--argc > 0)   //可一次查询多个目录
            isFile(*++argv);  //循环调用该函数处理各个命令传入的目录
    return 0;
}

5.重定向

dup 和 dup2函数
int dup(int oldfd); 
成功:返回一个新文件描述符;失败:-1设置errno为相应值

int dup2(int fd1, int fd2); 
# 将旧的描述符拷贝到新的,指向同一块空间,成功则返回一个新的描述符fd2
o  如果 fd2已经是被打开的文件描述符且不等于fd,则先将其关闭,然后再打开(注意关闭再打开是一个原子操作)
o  如果 fd2等于fd,则直接返回fd2(也等于fd),而不作任何操作

cat test.c > new.c
# 将test.c内容重定向输入到new.c文件中
--->  dup2(fd,STDOUT_FILENO)

dup:

dup2:

fcntl实现dup:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2167428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WSL进阶体验:gnome-terminal启动指南与中文显示问题一网打尽

起因 我们都知道 wsl 启动后就死一个纯命令行终端&#xff0c;一直以来我都是使用纯命令行工具管理Linux的。今天看到网上有人在 wsl 中启动带图形界面的软件。没错&#xff0c;就是在wsl中启动带有图形界面的Linux软件。比如下面这个编辑器。 ​​ 出于好奇&#xff0c;我就…

革新体验:细数3D在线预览在多个行业的广泛应用

‌3D在线预览展示技术的应用领域非常广泛&#xff0c;涵盖了从电子商务、产品设计、建筑设计到文化遗产保护等多个方面。‌ ‌1、电子商务‌&#xff1a; 在电商领域&#xff0c;3D展示技术为商品提供了全方位的展示&#xff0c;包括产品的外观、功能和卖点。这种交互式的购物…

影刀RPA实战:java结合影刀同步采购订单数据

1.实战目标 本次实战我们用java语言结合影刀&#xff0c;实现从自用ERP系统同步订单到旺店通中&#xff0c;在工作中&#xff0c;有时候我们的运营数据不是直接在旺店通ERP中操作&#xff0c;比如我们有自己的ERP&#xff0c;完成一些特定的内部工作后&#xff0c;再把数据同步…

做一个能适配「手机」的网站需要注意什么

这个问题的答案其实简单。 只要在网站前端开发过程中&#xff0c;将网站做成响应式布局&#xff0c;也就是 RWD &#xff08;Responsive Web Design&#xff09;就可以啦&#xff01;当手机或者不同设备打开网站时&#xff0c;通过检测视口分辨率来自动呈现不同的尺寸布局内容…

小程序弹出框是没办法遮挡住底部的tabbar的,解决的办法是使用自定义tabbar。。uni-app小程序如何自定义tabbar

原生小程序方法自定义 tabBar | 微信开放文档 如果是uni-app的小程序应该怎么自定义呢&#xff1f; 不是用page.json里面的tabbar就需要修改page.json.加上 "custom": true 注意list数组还是按照正常的来写。所以不使用但是也不能删除。 我们知道uni-app里面的页…

数字人形象自定义制作:readyplayer

网址&#xff1a; https://readyplayer.me/ 支持上传照片和拍照&#xff0c;会自动识别变成卡通风格 其他选项是配置选项&#xff1a;穿着、样貌等 上面弄好后右上角点击next&#xff0c;创建的模型可以下载3d glb文件 glb文件在线打开&#xff1a; https://gltf-viewer.d…

docker-文件复制(docker cp:用于在Docker主机和容器之间拷贝文件或目录)

文章目录 1、把宿主机的文件复制到容器内部1.1、查询 宿主机 root 下的文件1.2、docker cp /root/anaconda-ks.cfg spzx-redis:/root1.3、查看 spzx-redis 容器 中/root目录下是否有 anaconda-ks.cfg 文件 2、把容器中的文件 复制 到宿主机中2.1、查看 spzx-redis 容器 / 下的文…

Spring Boot框架在甘肃非遗文化网站设计中的运用

3 系统分析 当用户确定开发一款程序时&#xff0c;是需要遵循下面的顺序进行工作&#xff0c;概括为&#xff1a;系统分析–>系统设计–>系统开发–>系统测试&#xff0c;无论这个过程是否有变更或者迭代&#xff0c;都是按照这样的顺序开展工作的。系统分析就是分析系…

力扣面试150 添加与搜索单词 - 数据结构设计 字典树

Problem: 211. 添加与搜索单词 - 数据结构设计 &#x1f469;‍&#x1f3eb; 参考题解 public class WordDictionary {// 定义一个内部类 Node&#xff0c;用于表示 Trie&#xff08;前缀树&#xff09;中的每个节点class Node{// 每个节点有一个大小为 26 的数组&#xff0c…

详解swoole框架快速入门

Swoole包含两个主要部分&#xff1a;一个是用C语言开发的PHP扩展&#xff0c;作为核心功能&#xff1b;另一个是通过PHP代码编写的框架&#xff0c;类似于yii、TP和Laravel。 Swoole扩展本身具备web服务器功能&#xff0c;可以取代php-fpm。当仅使用Swoole框架时&#xff0c;可…

国产人形机器人突破,教会人形机器人如何像人类一样移动

与远在大洋彼岸的特斯拉机器人使用相同的训练设备&#xff0c;Humanoid Robot(上海)有限公司正在使用Xsens动作捕捉系统和ai训练人形机器人模仿人类运动&#xff0c;执行复杂任务。 关键要点: 人形机器人市场正在快速扩张:人形机器人市场将在未来大幅增长&#xff0c;据统计数…

傅里叶变换的python实现

周期信号的频谱   为了能既方便又明白地表示一个信号在不同频率下的幅值和相位&#xff0c;可以采用成为频谱图的表示方法。   在傅里叶分析中&#xff0c;把各个分量的幅度|Fn|或 Cn 随着频率nω1的变化称为信号的幅度谱。   而把各个分量的相位 φn 随角频率 nω1 变化…

ZUploader 之 文件上传

文件上传是前端开发很常用的一个功能, 通常文件上传都是异于表单提交, 使用起来配置繁多, 校验不统一, 展示不统一。 效果对比 特点 简化使用数据双向绑定样式统一带预览和下载功能 依赖 封装的组件 FileViewDialog (文件预览与下载,不需要此功能的话,可删除) 文件返回接口…

用户体验分享 | YashanDB V23.2.3安装部署

近期崖山新版体验过程中&#xff0c;总能看到用户提问&#xff1a;openssl版本问题、monit命令找不到问题、yashan用户权限问题、数据库重装问题 今日整理了多位用户的安装经验&#xff0c;希望能够帮助到大家~ 1.Lucifer三思而后行 &#xff1a;YashanDB 个人版数据库安装部…

稳居赛道销量前三的制造业巨头:数据安全建设的高效实践

作为一家迅速扩展的全球化制造企业&#xff0c;我们的分支和业务遍布国内多个城市及海外&#xff0c;员工流动频繁&#xff0c;终端设备多样&#xff0c;研发流程复杂。因此&#xff0c;我们需要一个灵活且强大的数据安全策略。经过深入的市场调研和严格POC测试&#xff0c;我们…

使用Postman搞定各种接口token实战

现在许多项目都使用jwt来实现用户登录和数据权限&#xff0c;校验过用户的用户名和密码后&#xff0c;会向用户响应一段经过加密的token&#xff0c;在这段token中可能储存了数据权限等&#xff0c;在后期的访问中&#xff0c;需要携带这段token&#xff0c;后台解析这段token才…

虚拟机的安装和使用

一、虚拟机的简单介绍 虚拟机可以使你在一台机器上同时运行二个或更多Windows、LINUX等系统&#xff0c;它可以模拟一个标准PC环境。这个环境和真实的计算机一样&#xff0c;都有芯片组、CPU、内存、显卡、声卡、网卡、软驱、硬盘、光驱、串口、并口、USB控制器等。 二、虚拟机…

案例|高动态厘米级监测!广东这些长大桥有了北斗“守护者”

随着桥梁交通流量快速提升&#xff0c;加上受到恶劣使用环境、荷载作用、年限过长等因素影响&#xff0c;近年来&#xff0c;因桥梁损害引发的安全事故时有发生。伴随着传感设备、数字通讯网络、数据分析方法等新技术和新设备的发展&#xff0c;为桥梁管养提供了更多有效的检测…

09_行级锁的加锁流程

MySQL 的加锁流程 文章目录 MySQL 的加锁流程简介记录锁、间隙锁和临键锁概述行级锁加锁流程示例流程两个原则&#xff0c;两个优化&#xff0c;一个 BUG两个原则两个优化一个 BUG示例1-主键&#xff08;唯一&#xff09;索引示例 2-普通索引 总结 简介 在 MySQL InnoDB 存储引…

理解C语言之深入理解指针(三)

目录 1. 字符指针变量 2. 数组指针变量 2.1 数组指针变量是什么&#xff1f; 2.2 数组指针变量怎么初始化 3. ⼆维数组传参的本质 4. 函数指针变量 4.1 函数指针变量的创建 4.2 函数指针变量的使⽤ 4.3 两段有趣的代码 4.3.1 typedef 关键字 5. 函数指针数组 6. 转移…