Linux系统编程-文件系统
目录
什么是Linux文件系统
文件系统的职责
存储介质抽象
inode:文件系统的核心
文件分配策略
目录结构
文件系统布局
日志和恢复机制
目录权限
粘滞位(t位):
硬链接和符号链接
硬链接的特点:
创建硬链接:
符号链接的特点:
创建符号链接:
文件属性
1.stat
2.fstat
3.lstat
4.chmod&fchmod
目录操作
目录的创建和销毁
更改当前工作路径
目录流操作
日期和时间
1.time
2.gmtime
3.localtime
4.strftime
/etc目录下的文件
/etc/passwd
etc/group
/etc/shadow
GLOB函数
利用glob实现du功能
利用glob实现shell的ls功能
什么是Linux文件系统
在操作系统的世界中,文件系统扮演着至关重要的角色,它负责管理磁盘上的数据,提供数据持久化和访问的机制。Linux文件系统,以其强大的灵活性和高性能,成为了许多系统管理员和开发者的首选。本文将从底层角度,深入探讨Linux文件系统的内部工作原理。
文件系统的职责
首先,让我们明确文件系统的基本职责:
1. 数据持久化:将数据从易失性的内存转移到非易失性的存储介质上。
2. 数据访问:提供一种机制,允许用户和应用程序读取和写入数据。
3. 数据组织:以一种逻辑和层次化的方式组织数据,通常以目录和文件的形式呈现。
存储介质抽象
Linux文件系统将物理存储介质抽象为逻辑存储单元,这个过程涉及到几个关键概念:
块设备:文件系统通过块设备接口与磁盘交互,块设备提供了一个统一的接口来处理不同类型存储设备的I/O操作。
缓冲区:为了提高I/O效率,文件系统使用缓冲区暂存即将写入磁盘或从磁盘读取的数据。
inode:文件系统的核心
每个文件或目录在Linux文件系统中都有一个对应的inode(索引节点)。inode包含了文件的元数据,而不是文件的数据本身。这包括:
文件大小
权限(所有者、组、其他)
时间戳(创建、访问、修改时间)
数据块索引
文件分配策略
文件系统需要决定如何将文件数据分配到磁盘上的数据块。这涉及到多种文件分配策略:
连续分配:在早期的文件系统中使用,将文件数据存储在连续的磁盘块中。
链式分配:每个数据块包含指向下一个数据块的指针。
索引分配:使用一个索引块来记录数据块的位置。
现代文件系统,如Ext4和XFS,采用更为复杂的分配策略,以提高性能和灵活性。
目录结构
Linux文件系统的目录结构由目录项(Dentry)实现,每个目录项包含:
文件或目录的名称
指向对应inode的指针
这种结构使得文件和目录的查找变得非常高效。
文件系统布局
在磁盘上,文件系统的布局通常包括:
超级块:包含文件系统的全局信息,如块大小、inode数量等。
inode表:存储所有inode的区域。
数据块区:存储文件数据的区域。
日志和恢复机制
现代文件系统使用日志来记录文件系统的操作,这有助于在系统崩溃后恢复文件系统的状态。例如,Ext4文件系统使用journaling来保证数据的一致性。
目录权限
在Linux中,目录权限通常以10个字符的字符串表示,例如-drwxrwxrwt。这个字符串从左到右的含义如下:
第一个字符:
     d:目录(directory)。
     -:普通文件(regular file)。
     l:符号链接(symbolic link)。
     b:块设备文件(block device)。
     c:字符设备文件(character device)。
     p:管道文件(named pipe,FIFO)。
     s:套接字文件(socket)
接下来的三组字符(每组三个字符):
     第一组表示所有者的权限(owner)。
     第二组表示与所有者同一组的用户的权限(group)。
     第三组表示其他所有用户的权限(others)。
     其中r(4)表示可读,w(2)可写,x(1)可执,s表示权限切换user
特殊权限位:
     如果在第三组权限的末尾有一个 t,则表示设置了粘滞位。
 粘滞位(t位):
 
在Linux系统中通常被称为 "t" 位,是一种特殊的文件系统权限位,它对目录的行为有特定的影响。当对目录设置了粘滞位后,只有该目录的拥有者和文件的所有者才能删除或者重命名目录中的文件。
 粘滞位的主要作用:
     1.防止删除和重命名:如果一个目录设置了粘滞位,那么只有文件的所有者和目录的所有者可以删除或者重命名该目录下的文件。这可以防止普通用户删除或重命名其他用户在该目录下的文件。
     2.保护公共目录:粘滞位通常用于公共目录,如 /tmp,以确保用户可以创建临时文件,但不能删除或重命名其他用户的临时文件。
 如何设置粘滞位:
         在Linux系统中,可以通过 chmod 命令来设置粘滞位。设置粘滞位的命令格式如下:
chmod +t <directory>硬链接和符号链接
硬链接(Hard Link)是一种文件链接方式,它直接指向文件的数据所在的位置,即文件系统中的inode(索引节点)。硬链接不是文件的副本,它与原始文件共享相同的inode和数据块。这意味着硬链接和原始文件是完全相同的,对硬链接的修改实际上是对原始文件的修改,反之亦然。硬链接在文件系统管理、备份和数据恢复等场景中非常有用,因为它们提供了对原始数据的直接访问,而不需要复制数据。然而,由于硬链接的特性,使用时也需要谨慎,以避免意外覆盖或删除重要文件。可以使用stat查询Links数,即inode硬链接数量。
硬链接的特点:
        1.共享inode:硬链接共享相同的inode和数据块,因此它们具有相同的inode号。
         2.文件名无关:硬链接可以位于不同的目录中,与文件名无关。硬链接的创建不会影响文件的目录结构。
         3.不可跨文件系统:硬链接不能跨越不同的文件系统创建。硬链接必须位于与原始文件相同的文件系统中。
          4.删除行为:只有当指向同一个inode的所有硬链接都被删除后,文件的数据才会被系统释放。删除硬链接不会删除原始文件或其它硬链接。
          5.不适用于目录和分区:硬链接通常不用于目录,因为目录的硬链接可能导致文件系统中的循环,从而引发问题。
创建硬链接:
在Linux中,可以使用 ln 命令创建硬链接,命令格式如下:
ln existing_file new_link这里的 existing_file 是已存在的文件,new_link 是要创建的硬链接的名称。
         符号链接(Symbolic Link,也称为Symlink)是一种特殊的文件类型,它包含了指向另一个文件或目录的路径。符号链接可以视为一个快捷方式,它允许用户通过链接访问目标文件或目录,就像直接访问原始文件或目录一样。
 Blocks为0不占内存空间
符号链接的特点:
    1.包含路径:符号链接是一个单独的文件,包含了指向另一个文件或目录的路径。
     2.跨文件系统:符号链接可以跨越不同的文件系统,这与硬链接不同。
     3.目录和文件:符号链接可以指向文件或目录。
     4.删除独立性:删除符号链接不会影响它所指向的原始文件或目录。
     5.更新和移动:如果原始文件或目录被移动或重命名,符号链接将变为死链接(dangling symlink),即它指向的路径不再有效。
     6.权限继承:符号链接的权限与原始文件或目录的权限无关,但访问符号链接时的权限检查会应用到目标文件或目录。
创建符号链接:
在Linux中,可以使用 ln 命令的 -s 选项创建符号链接,命令格式如下:
 ln -s target_path link_name这里的 target_path 是要链接的目标文件或目录的路径,link_name 是符号链接的名称。
文件属性
1.stat
int stat(const char *pathname, struct stat *statbuf);通过文件路径获取属性信息填入 struct stat中,成功返回0,失败返回-1
2.fstat
int fstat(int fd, struct stat *statbuf);通过文件描述符获取属性信息填入 struct stat中,成功返回0,失败返回-1
3.lstat
int lstat(const char *pathname, struct stat *statbuf);struct stat {dev_t st_dev;         /* 包含文件的设备的ID */ino_t st_ino;         /* inode(索引节点)编号 */mode_t st_mode;       /* 16位的位图,表示文件类型,文件访问权限,特殊权限位 */nlink_t st_nlink;     /* 硬链接的数量 */uid_t st_uid;         /* 所有者的用户名ID */gid_t st_gid;         /* 所有者的组ID */dev_t st_rdev;        /* 特殊文件的设备ID */off_t st_size;        /* 总大小,单位为字节 */blksize_t st_blksize; /* 文件系统I/O的块大小 */blkcnt_t st_blocks;  /* 分配的512B块的数量 *//* 自 Linux 2.6 起,内核支持以下时间戳字段的纳秒级精度。有关 Linux 2.6 之前的详细信息,请参阅注释。 */struct timespec st_atim;  /* 最后访问时间 */struct timespec st_mtim;  /* 最后修改时间 */struct timespec st_ctim;  /* 最后状态改变时间 */#define st_atime st_atim.tv_sec      /* 向后兼容 */#define st_mtime st_mtim.tv_sec#define st_ctime st_ctim.tv_sec
};面对符号链接文件时获取的是符号链接文件的属性。
4.chmod&fchmod
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);改变权限,成功返回0,失败-1
S_ISUID (04000) 设置用户ID(在调用 execve(2) 时设置进程有效用户ID)
S_ISGID (02000) 设置组ID(在调用 execve(2) 时设置进程有效组ID;强制性锁定,如 fcntl(2) 中所述;从父目录获取新文件的组,如 chown(2) 和 mkdir(2) 中所述)
S_ISVTX (01000) 粘滞位(限制删除标志,如 unlink(2) 中所述)
S_IRUSR (00400) 所有者读取
S_IWUSR (00200) 所有者写入
S_IXUSR (00100) 所有者执行/搜索("搜索"适用于目录,意味着可以访问目录内的条目)
S_IRGRP (00040) 组内成员读取
S_IWGRP (00020) 组内成员写入
S_IXGRP (00010) 组内成员执行/搜索
S_IROTH (00004) 其他用户读取
S_IWOTH (00002) 其他用户写入
S_IXOTH (00001) 其他用户执行/搜索
目录操作
目录的创建和销毁
int mkdir(const char *pathname, mode_t mode);创建一个新目录。如果目录的父目录不存在,或者没有足够的权限,函数将失败。
int rmdir(const char *pathname);删除一个空目录。如果目录非空,或者指定路径不存在,或者没有足够的权限,函数将失败。
更改当前工作路径
int chdir(const char *path);改变(切换)当前工作目录到指定的路径。如果路径不存在或没有足够的权限访问该路径,函数将失败。
int fchdir(int fd);
改变当前工作目录到由文件描述符 fd 指向的目录。
char *getcwd(char *buf, size_t size);获取当前工作目录的绝对路径,并将其复制到由 buf 指向的缓冲区中。如果缓冲区大小不足以存储路径,函数将失败。
目录流操作
DIR *opendir(const char *name);
DIR *fdopendir(int fd);打开文件夹获取DIR流指针,失败返回NULL
struct dirent *readdir(DIR *dirp);struct dirent {ino_t d_ino;       /* inode编号 */off_t d_off;       /* 并非偏移量;详见下文 */unsigned short d_reclen; /* 此记录的长度 */unsigned char d_type; /* 文件类型;并非所有文件系统类型都支持 */char d_name[256]; /* 以空字符结尾的文件名 */};返回指向struct dirent指针,dirent里存储了目录的信息,失败返回空指针
日期和时间
1.time
time_t time(time_t *tloc);时间戳是从 1970 年 1 月 1 日(UTC 时间)开始计算的Unix 时间戳,tloc如果提供了这个参数,函数会将当前时间的时间戳存储在这个指针指向的位置。如果这个参数是 NULL 或者没有提供,函数不会写入任何值。
2.gmtime
struct tm *gmtime(const time_t *timep);struct tm {int tm_sec;    /* Seconds (0-60) */int tm_min;    /* Minutes (0-59) */int tm_hour;   /* Hours (0-23) */int tm_mday;   /* Day of the month (1-31) */int tm_mon;    /* Month (0-11) */int tm_year;   /* Year - 1900 */int tm_wday;   /* Day of the week (0-6, Sunday = 0) */int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */int tm_isdst;  /* Daylight saving time */
};Unix时间转为tm结构体,该结构体表示的是协调世界时UTC
3.localtime
struct tm *localtime(const time_t *timep);Unix时间转为tm结构体,会根据本地时区和夏令时调整来转换时间
4.strftime
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);根据给定的格式字符串,将 tm 结构体中的时间信息格式化为可读的字符串,并将其存储在提供的字符数组 s 中
参数
s:指向字符数组的指针,用于存储格式化后的字符串。
max:s 数组的最大长度,即可以存储的最大字符数,包括空字符('\0')。
format:一个格式字符串,指定了时间的格式化方式。格式字符串中可以包含特殊的格式说明符,如 %Y 表示四位数的年份等。
tm:指向 tm 结构体的指针,包含了要格式化的时间信息。返回值
函数返回实际写入到 s 数组中的字符数(不包括结尾的空字符)。如果由于缓冲区大小不足而无法写入整个字符串,返回值会小于 max。如果 s 是 NULL 或 max 是 0,则函数不执行格式化操作,但仍然会返回需要的缓冲区大小(不包括结尾的空字符)。格式化说明符
%a:缩写的星期名称。
%A:完整的星期名称。
%b:缩写的月份名称。
%B:完整的月份名称。
%c:适合人类可读的日期和时间。
%d:月份中的第几天(01-31)。
%H:小时(24小时制,00-23)。
%I:小时(12小时制,01-12)。
%m:月份(01-12)。
%M:分钟(00-59)。
%S:秒(00-59)。
%Y:四位数的年份。
/etc目录下的文件
/etc/passwd
文件中的每行都包含一个用户账户的信息,字段之间用冒号(:)分隔。标准的字段包括:
        -用户名:用户的登录名。
         -密码:通常是一个“x”字符,表示密码存储在 /etc/shadow 文件中,或者是加密后的密码散列值。
         -用户ID(UID):用户的唯一标识符,通常是数字。
         -组ID(GID):用户所属主组的唯一标识符。
         -主目录:用户的主目录路径。
         -登录shell:用户登录时使用的 shell。
格式示例如下:
     username:x:UID:GID:User Name:/home/username:/bin/bash
具体解释如下:
     username:用户的登录名。
     x:表示密码存储在 /etc/shadow 文件中。
     UID:用户的唯一标识符。
     GID:用户所属主组的唯一标识符。
     User Name:用户的全名或描述。
     /home/username:用户的主目录路径。
     /bin/bash:用户的默认登录 shell。
struct passwd *getpwnam(const char *name);struct passwd {char   *pw_name;       /* username */char   *pw_passwd;     /* user password */uid_t   pw_uid;        /* user ID */gid_t   pw_gid;        /* group ID */char   *pw_gecos;      /* user information */char   *pw_dir;        /* home directory */char   *pw_shell;      /* shell program */
};通过用户名获取用户信息
struct passwd *getpwuid(uid_t uid);通过用户uid获取用户信息
etc/group
是 Linux 和类 Unix 系统中的另一个重要文件,它用于存储用户组的信息。每个条目代表一个用户组,并且每行的字段通常由冒号(:)分隔。标准的字段包括:
        -组名:用户组的名称,通常不包含空格。
         -密码:用户组的加密密码,或者是一个“x”字符,表示密码存储在 /etc/gshadow 文件中。
         -组ID(GID):用户组的唯一标识符,是一个数字。
         -用户列表:属于该组的用户列表,可以是用户名或用户名的逗号分隔列表。
格式示例如下:
          groupname:password:GID:user1,user2,user3
具体解释如下:
     groupname:用户组的名称。
     password:用户组的加密密码,或者是一个“x”字符表示密码存储在 /etc/gshadow 文件中。
     GID:用户组的唯一标识符。
     user1,user2,user3:属于该组的用户列表,用户之间用逗号分隔。
struct group *getgrnam(const char *name);struct group {char   *gr_name;        /* group name */char   *gr_passwd;      /* group password */gid_t   gr_gid;         /* group ID */char  **gr_mem;         /* NULL-terminated array of pointersto names of group members */
};通过组名获取组信息
struct group *getgrgid(gid_t gid);通过组gid获取组信息
/etc/shadow
文件在类 Unix 系统中用于存储用户账户的密码信息,以增强安全性。该文件通常只能由 root 用户访问,并且包含加密后的密码数据。每行对应一个用户,字段之间用冒号(:)分隔。标准的字段包括:
        -用户名:与 /etc/passwd 文件中的用户名相同。
         -加密密码:用户的加密密码或一个特定的值,如 * 或 !,表示账户被锁定或密码无效。
         -最后一次更改密码的日期:以从1970年1月1日(epoch)开始的天数计算。
         -密码最小更改间隔:用户必须等待的最小天数,才能再次更改密码。
         -密码最大有效期限:密码的最大有效天数。
         -密码警告期:在密码过期前,系统会警告用户的天数。
         密码到期后账户被禁用的天数:密码过期后,用户账户被禁用的天数。
         -预留字段:通常为空。
格式示例如下:
        username:$6$somehash$somehash:17000:0:99999:7:7:::
具体解释如下:
     username:用户的登录名。
     $6$somehash$somehash:加密的密码,其中 $6$ 表示使用的是 SHA-512 加密算法。
     17000:最后一次更改密码的日期(天数)。
     0:密码最小更改间隔。
     99999:密码最大有效期限。
     7:密码警告期。
     7:密码到期后账户被禁用的天数。
     :::预留字段,通常为空。
GLOB函数
int glob(const char *pattern, int flags,int (*errfunc) (const char *epath, int eerrno),glob_t *pglob);typedef struct {size_t gl_pathc;    /* 到目前为止匹配的路径数量 */char **gl_pathv;    /* 匹配的路径名列表 */size_t gl_offs;     /* 在 gl_pathv 中预留的槽位数 */
} glob_t;参数说明:
--pattern:一个指向以null结尾的字符串的指针,指定了要匹配的文件名模式(文件路径)。模式可以包含如下特殊字符:
*:匹配任意数量的字符。
?:匹配任意单个字符。
[...]:匹配括号内的任意一个字符。--flags:用于控制glob函数行为的标志位,可以是以下值的组合:
GLOB_APPEND:如果pglob已经包含一些路径,新的路径将被追加到现有列表中,没有APPEND则是覆盖。
GLOB_DOOFFS:减少分配给pglob->gl_pathv数组的内存量,数组大小为pglob->gl_pathc + 1。
GLOB_ERR:如果发生错误并且提供了错误函数,函数将立即调用错误处理函数。
GLOB_MARK:在每个匹配的路径名末尾添加一个斜杠(/)。
GLOB_NOCHECK:如果模式没有匹配任何文件,返回空列表而不是GLOB_NOMATCH错误。
GLOB_NOSORT:不按字母顺序对匹配的路径进行排序。--errfunc:当出现错误并且GLOB_ERR标志被设置时,将调用此错误处理函数。该函数接受两个参数:错误路径和错误号。不需要错误检查时可以设置NULL。
--pglob:指向glob_t结构的指针,该结构用于存储匹配的路径列表和相关信息。
返回值:
成功时,返回 0。
当没有找到匹配的文件名时,如果设置了GLOB_NOCHECK标志,返回 0,否则返回 GLOB_NOMATCH。
发生错误时,返回非零错误代码。
void globfree(glob_t *pglob);销毁pglob申请空间,主要是char **gl_pathv;字符数组申请的空间
利用glob实现du功能
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>#define PATHSIZE 128static path_noloop(const char *path) {char *pos;pos = strrchr(path, '/')'if(pos == NULL)exit(1);if(strcmp(pos+1, ".") == 0 || strcmp(pos+1, "..") == 0)return 0;return 1;
}static int64_t K_du(const char* path){struct stat statres;//非目录if(lstat(path, &statres) < 0 ){perror("lstat()");exit(1);}if(!S_ISDIR(statres.st_mode))return statres.st_blocks/2;//目录char *nextpath[PATHSIZE];glob_t globres;int sum = statres.st_blocks;strncpy(nextpath, path, PATHSIZE);strncat(nextpath, "/*", PATHSIZE);glob(nextpath, 0, NULL, &globres);strncpy(nextpath, path, PATHSIZE);strncat(nextpath, "/.*", PATHSIZE);glob(nextpath, GLOB_APPEND, NULL, &globres);for(int i = 0; i < globres.gl_pathc; i++){if(path_noloop(globres.gl_pathv[i]))sum += mydu(globres.gl_pathv[i]);}return sum;
}利用glob实现shell的ls功能
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <glob.h>
#include <sys/wait.h>// 定义命令分隔符
#define DELIMS " \t\n"// 定义一个结构体,用于存储 glob 函数的返回结果
struct cmd_st {glob_t globres;
};// promopt 函数用于显示提示符
static void promopt(void) {printf("[myshell-knoci-1.2] $ ");
}// parse 函数用于解析用户输入的命令行
static void parse(char *line, struct cmd_st *cmd) {char *token;  // 用于存储分割出的每个单词int i = 0;    // 用于控制是否追加到 glob 结构// 使用 strsep 函数分割字符串,直到没有更多单词while(1) {token = strsep(&line, DELIMS);if (token == NULL)break;if(token[0] == '\0')  // 跳过空字符串continue;// 对每个分割出的单词进行 glob 匹配,第一个单词不追加,后续追加glob(token, GLOB_NOCHECK | (i ? GLOB_APPEND : 0), NULL, &cmd->globres);i = 1;}
}// 主函数
int main(int argc, char *argv[]) {char *linebuf = NULL;  // 用于存储 getline 读取的整行命令size_t linebuf_size = 0; // linebuf 的当前分配大小struct cmd_st cmd;      // 定义 cmd 结构用于存储 glob 结果// 初始化 glob 结构的指针和计数器cmd.globres.gl_pathv = NULL;cmd.globres.gl_pathc = 0;pid_t pid;  // 存储 fork 函数返回的子进程 ID// 无限循环,持续读取和执行用户命令while(1) {promopt();  // 显示提示符// 使用 getline 函数从标准输入读取一行if(getline(&linebuf, &linebuf_size, stdin) < 0)break;// 解析命令行parse(linebuf, &cmd);// 假设没有内部命令,所有命令都是外部命令pid = fork();  // 创建子进程if(pid < 0) {perror("fork");  // 显示 fork 出错信息exit(1);}// 在子进程中执行命令if(pid == 0) {// 子进程中调用 execvp 执行命令if(cmd.globres.gl_pathc > 0) {execvp(cmd.globres.gl_pathv[0], cmd.globres.gl_pathv);}perror("execvp");  // 如果 execvp 失败,显示错误信息exit(1);  // 退出子进程} else {// 父进程等待子进程结束int status;waitpid(pid, &status, 0);}}// 清理资源globfree(&cmd.globres);  // 释放 glob 分配的内存free(linebuf);  // 释放 getline 分配的内存exit(0);  // 正常退出程序
}相关文章:
Linux系统编程-文件系统
目录 什么是Linux文件系统 文件系统的职责 存储介质抽象 inode:文件系统的核心 文件分配策略 目录结构 文件系统布局 日志和恢复机制 目录权限 粘滞位(t位): 硬链接和符号链接 硬链接的特点: 创建硬链接: 符号链接的…...
 
【解决】ubuntu20.04 root用户无法SSH登陆问题
Ubuntu root用户无法登录的问题通常可以通过修改SSH配置文件和系统登录配置来解决。 修改SSH配置文件 sudo vim /etc/ssh/sshd_config 找到 PermitRootLogin 设置,并将其值更改为 yes 以允许root用户通过SSH登录 保存并关闭文件之后,需要重启SSH服务…...
 
(前缀和) LeetCode 238. 除自身以外数组的乘积
一. 题目描述 原题链接 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&…...
 
【JVM基础05】——组成-能不能解释一下方法区?
目录 1- 引言:方法区概述1-1 方法区是什么?(What)1-2 为什么用方法区?方法区的作用 (Why) 2- ⭐核心:详解方法区(How)2-1 能不能解释一下方法区?2-2 元空间内存溢出问题2-3 什么是常量池?2-4 运行时常量池 …...
 
前端:Vue学习-3
前端:Vue学习-3 1. 自定义指令2. 插槽2.1 插槽 - 后备内容(默认值)2.2 插槽 - 具名插槽2.3 插槽 - 作用域插槽 3. Vue - 路由3.1 路由模块封装3.2 声明式导航 router-link 高亮3.3 自定义匹配的类名3.4 声明式导肮 - 跳转传参3.5 Vue路由 - 重…...
 
npm 安装报错(已解决)+ 运行 “wue-cli-service”不是内部或外部命令,也不是可运行的程序(已解决)
首先先说一下我这个项目是3年前的一个项目了,中间也是经过了多个人的修改惨咋了布置多少个人的思想,这这道我手里直接npm都安装不上,在网上也查询了多种方法,终于是找到问题所在了 问题1: 先是npm i 报错在下面图片&…...
 
江苏科技大学24计算机考研数据速览,有专硕复试线大幅下降67分!
江苏科技大学(Jiangsu University of Science and Technology),坐落在江苏省镇江市,是江苏省重点建设高校,江苏省人民政府与中国船舶集团有限公司共建高校,国家国防科技工业局与江苏省人民政府共建高校 &am…...
 
20分钟上手新版Skywalking 9.x APM监控系统
Skywalking https://skywalking.apache.org/ Skywalking是专为微服务、云原生和基于容器的(Kubernetes)架构设计的分布式系统性能监控工具。 Skywalking关键特性 ● 分布式跟踪 ○ 端到端分布式跟踪。服务拓扑分析、以服务为中心的可观察性和API仪表板。…...
 
【07】LLaMA-Factory微调大模型——微调模型导出与微调参数分析
上文介绍了如何对微调后的模型进行使用与简单评估。本文将介绍对微调后的模型进行导出的过程。 一、llama-3微调后的模型导出 首先进入虚拟环境,打开LLaMA-Factory的webui页面 conda activate GLM cd LLaMA-Factory llamafactory-cli webui 之后,选择…...
 
动态路由协议 —— EIGRP 与 OSPF 的区别
EIGRP(增强内部网关路由协议)和 OSPF(开放式最短路径优先)是两种最常见的动态路由协议,主要是用来指定路由器或交换机之间如何通信。将其应用于不同的情况下,可提高速率、延迟等方面的性能。那么它们之间到…...
 
【中项】系统集成项目管理工程师-第5章 软件工程-5.1软件工程定义与5.2软件需求
前言:系统集成项目管理工程师专业,现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试,全称为“全国计算机与软件专业技术资格(水平)考试”&…...
HarmonyOS应用开发者高级认证,Next版本发布后最新题库 - 多选题序号1
基础认证题库请移步:HarmonyOS应用开发者基础认证题库 注:有读者反馈,题库的代码块比较多,打开文章时会卡死。所以笔者将题库拆分,单选题20个为一组,多选题10个为一组,题库目录如下,…...
 
Windows11(24H2)LTSC长期版下载!提前曝光Build26100?
系统;windows11 文章目录 前言一、LTSC是什么?二、 Windows 11 Vision 24H2 LTSC 的版本号为 Build 26100,镜像中提供以下三个 SKU:总结 前言 好的系统也能给你带来不一样的效果。 一、LTSC是什么? & & L…...
 
【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十三章 驱动模块传参
i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…...
uniapp 小程序 支付逻辑处理
uniapp 小程序 支付逻辑处理 上代码如果你不需要支付宝适配,可以删除掉支付宝的条件判断代码 <button class"subBtn" :disabled"submiting" click"goPay">去支付</button>// 以下代码你需要改的地方// 1. order/app/v1…...
scikit-learn库学习之make_regression函数
scikit-learn库学习之make_regression函数 一、简介 make_regression是scikit-learn库中用于生成回归问题数据集的函数。它主要用于创建合成的回归数据集,以便在算法的开发和测试中使用。 二、语法和参数 sklearn.datasets.make_regression(n_samples100, n_feat…...
 
经典文献阅读之--World Models for Autonomous Driving(自动驾驶的世界模型:综述)
Tip: 如果你在进行深度学习、自动驾驶、模型推理、微调或AI绘画出图等任务,并且需要GPU资源,可以考虑使用UCloud云计算旗下的Compshare的GPU算力云平台。他们提供高性价比的4090 GPU,按时收费每卡2.6元,月卡只需要1.7元每小时&…...
孙健提到的实验室的研究方向之一是什么?()
孙健提到的实验室的研究方向之一是什么?() 点击查看答案 A.虚拟现实B.环境感知和理解 C.智能体博弈D.所有选项都正确 图灵奖是在哪一年设立的?() A.1962B.1966 C.1976D.1986 孙健代表的实验室的前身主要研究什么?&…...
初级java每日一道面试题-2024年7月23日-Iterator和ListIterator有什么区别?
面试官: Iterator和ListIterator有什么区别? 我回答: Iterator和ListIterator都是Java集合框架中用于遍历集合元素的接口,但它们之间存在一些关键的区别,主要体现在功能和使用场景上。下面我将详细解释这两种迭代器的不同之处: 1. Iterat…...
 
2024-07-23 Unity AI行为树2 —— 项目介绍
文章目录 1 项目介绍2 AI 代码介绍2.1 BTBaseNode / BTControlNode2.2 动作/条件节点2.3 选择 / 顺序节点 3 怪物实现4 其他功能5 UML 类图 项目借鉴 B 站唐老狮 2023年直播内容。 点击前往唐老狮 B 站主页。 1 项目介绍  本项目使用 Unity 2022.3.32f1c1,实现基…...
 
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
 
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
 
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
 
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
 
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
 
关于easyexcel动态下拉选问题处理
前些日子突然碰到一个问题,说是客户的导入文件模版想支持部分导入内容的下拉选,于是我就找了easyexcel官网寻找解决方案,并没有找到合适的方案,没办法只能自己动手并分享出来,针对Java生成Excel下拉菜单时因选项过多导…...
