当前位置: 首页 > news >正文

免费的行情网站app大全下载小程序传奇代理

免费的行情网站app大全下载,小程序传奇代理,it外包服务哪家好,网站做app用什么语言文章目录 C语言文件操作系统文件I/O接口介绍 open函数返回值文件描述符fd0 1 2文件描述符的分配规则 重定向使用 dup2 系统调用 FILE理解文件系统理解硬链接软链接acm 动态库和静态库静态库与动态库生成静态库生成动态库#xff1a; C语言文件操作 先来段代码回顾… 文章目录 C语言文件操作系统文件I/O接口介绍 open函数返回值文件描述符fd0 1 2文件描述符的分配规则 重定向使用 dup2 系统调用 FILE理解文件系统理解硬链接软链接acm 动态库和静态库静态库与动态库生成静态库生成动态库 C语言文件操作 先来段代码回顾C文件接口 hello.c写读文件 #include stdio.h #include string.h int main() {FILE *fp fopen(myfile, w);if(!fp){printf(fopen error!\n);}const char *msg hello bit!\n;int count 5;while(count--){fwrite(msg, strlen(msg), 1, fp);}fclose(fp);FILE *rfp fopen(myfile, r);if(!rfp){printf(fopen error!\n);}char buf[1024];const char *msg hello bit!\n;while(1){//注意返回值和参数此处有坑仔细查看man手册关于该函数的说明ssize_t s fread(buf, 1, strlen(msg), rfp);if(s 0){buf[s] 0;printf(%s, buf);}if(feof(fp)){break;}}fclose(fp);return 0; }输出信息到显示器你有哪些方法 #include stdio.h #include string.h int main() {const char *msg hello fwrite\n;fwrite(msg, strlen(msg), 1, stdout);printf(hello printf\n);fprintf(stdout, hello fprintf\n);return 0; }stdin stdout stderr C默认会打开三个输入输出流分别是stdin, stdout, stderr仔细观察发现这三个流的类型都是FILE*, fopen返回值类型的文件指针。 总结 打开文件的方式 如上是我们之前学的文件相关操作。还有 fseek ftell rewind 的函数在C部分已经有所涉猎。 系统文件I/O 操作文件除了上述C接口当然C也有接口其他语言也有我们还可以采用系统接口来进行文件访问先来直接以代码的形式实现和上面一模一样的代码 hello.c 写文件: #include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include unistd.h #include string.h int main() {umask(0);int fd open(myfile, O_WRONLY|O_CREAT, 0644);if(fd 0){perror(open);return 1;}int count 5;const char *msg hello bit!\n;int len strlen(msg);while(count--){write(fd, msg, len);//fd: 后面讲 msg缓冲区首地址 //len: 本次读取期望写入多少个字节的数据。 返回值实际写了多少字节数据}close(fd);return 0; }hello.c读文件 #include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include unistd.h #include string.h int main() {int fd open(myfile, O_RDONLY);if(fd 0){perror(open);return 1;}const char *msg hello bit!\n;char buf[1024];while(1){ssize_t s read(fd, buf, strlen(msg));//类比writeif(s 0){printf(%s, buf);}else{break;}}close(fd);return 0; }接口介绍 在Linux中open() 是一个系统调用函数用于打开或创建文件。它的原型如下 #include fcntl.hint open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);open() 函数接受两个参数第一个参数是要打开或创建的文件路径名字符串类型第二个参数是标志位指定了打开文件的方式和属性。 以下是常见的 flags 标志位选项 O_RDONLY只读模式。O_WRONLY只写模式。O_RDWR读写模式。O_CREAT如果文件不存在则创建新文件。O_TRUNC如果文件存在并且以可写方式打开则将其截断为空文件。O_APPEND以追加方式打开文件在已有内容末尾添加新数据。O_EXCL与 O_CREAT 一起使用时如果文件已经存在则失败返回。O_NONBLOCK非阻塞模式打开文件。 除了上述标志位之外还可以通过按位或运算符组合多个标志位来实现更复杂的操作。 如果使用了 O_CREAT 标志位那么需要提供一个额外的参数 mode 来设置文件权限。mode 参数是一个无符号整数表示文件的访问权限。常见的权限选项包括 S_IRUSR、S_IWUSR、S_IRGRP、S_IWGRP、S_IROTH 和 S_IWOTH分别表示用户、组和其他人的读写权限。 open() 函数返回一个整数值即文件描述符file descriptor。如果打开或创建文件成功则返回非负整数作为文件描述符否则返回-1 表示出错。 write的使用 在Linux中write() 是一个系统调用函数用于将数据写入文件描述符file descriptor。它的原型如下 #include unistd.hssize_t write(int fd, const void *buf, size_t count);write() 函数接受三个参数文件描述符 fd、要写入的数据缓冲区地址 buf 和要写入的字节数 count。 以下是 write() 函数的使用方式 #include unistd.hint fd open(filename.txt, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (fd ! -1) {const char* buffer Hello, World!;ssize_t bytes_written write(fd, buffer, strlen(buffer));if (bytes_written -1) {// 写入出错} else {// 成功写入指定字节数}close(fd); } else {// 文件打开或创建失败 }上述示例代码首先使用 open() 函数打开或创建了一个文件并获取到文件描述符 fd。然后定义一个字符串缓冲区 buffer 存储要写入的数据。接着通过调用 write() 函数将缓冲区中的数据写入文件。strlen(buffer) 表示写入的字节数为字符串长度。write() 函数返回实际写入的字节数如果返回值为-1则表示写入出错。 需要注意的是在使用完文件后应使用 close() 函数关闭文件描述符以释放相关资源。 write() 函数可以用于向文件、终端、套接字等支持写入操作的设备进行数据写入。它是一个底层的系统调用函数适用于对文件和设备进行较低级别的操作。 值得一提的是在C中您也可以使用 fstream 头文件提供的文件流std::ofstream来进行更方便和类型安全的文件写入操作。 read的使用方法 在Linux中read() 是一个系统调用函数用于从文件描述符file descriptor读取数据。它的原型如下 #include unistd.hssize_t read(int fd, void *buf, size_t count);read() 函数接受三个参数文件描述符 fd、存储读取数据的缓冲区地址 buf 和要读取的最大字节数 count。 以下是 read() 函数的使用方式 #include unistd.hint fd open(filename.txt, O_RDONLY); if (fd ! -1) {char buffer[1024];ssize_t bytes_read read(fd, buffer, sizeof(buffer));if (bytes_read -1) {// 读取出错} else if (bytes_read 0) {// 文件已经到达末尾} else {// 成功读取指定字节数// 可以对读取的数据进行处理}close(fd); } else {// 文件打开失败 }上述示例代码首先使用 open() 函数以只读模式打开文件并获取到文件描述符 fd。然后定义一个字符数组缓冲区 buffer 来存储读取的数据。接着通过调用 read() 函数将文件中的数据读取到缓冲区中。sizeof(buffer) 表示最多读取的字节数为缓冲区大小。read() 函数返回实际读取的字节数如果返回值为-1则表示读取出错。如果返回值为0表示文件已经到达末尾。 需要注意的是在使用完文件后应使用 close() 函数关闭文件描述符以释放相关资源。 read() 函数可以用于从文件、终端、套接字等支持读取操作的设备中获取数据。它是一个底层的系统调用函数适用于对文件和设备进行较低级别的操作。 close的用法 在Linux中close() 函数用于关闭打开的文件描述符file descriptor。它的原型如下 #include unistd.hint close(int fd);close() 函数接受一个整数参数 fd表示要关闭的文件描述符。 以下是 close() 函数的使用方法 #include unistd.hint fd open(filename.txt, O_RDONLY); if (fd ! -1) {// 对文件进行读取或写入操作int result close(fd);if (result -1) {// 关闭文件失败} } else {// 文件打开失败 }上述示例代码首先使用 open() 函数以只读模式打开文件并获取到文件描述符 fd。然后在执行其他对文件的读取或写入操作后调用 close() 函数来关闭文件描述符。如果 close() 函数返回值为-1则表示关闭文件失败。 需要注意的是close() 函数会释放与文件描述符相关联的资源包括操作系统内核维护的文件表项等。因此在不再需要使用文件时应该及时关闭文件描述符以避免资源泄漏和浪费。 请注意当进程终止时所有打开的文件描述符都会自动关闭所以通常情况下并不需要显式地调用 close() 函数。但是在长时间运行的程序中特别是涉及大量文件操作的程序中及时关闭不再需要的文件描述符是一个良好的编程习惯。 lseek的使用方法 在Linux中lseek() 函数用于设置文件偏移量file offset它可以改变对文件的读取或写入位置。lseek() 函数的原型如下 #include unistd.hoff_t lseek(int fd, off_t offset, int whence); /*off_t 是一个数据类型用于表示文件偏移量。它是在 unistd.h 头文件中定义的 通常被定义为 long int 类型。off_t 的目的是提供足够大的整数类型以便能够表示大 文件的偏移量。因为现代操作系统支持处理非常大的文件所以需要使用一个能够容纳大文件大小 的数据类型来表示偏移量。在不同的系统上off_t 可能会有不同的实现方式。例如在32位 系统上off_t 可能是一个32位的有符号整数int 或 long int而在64位系统上 off_t 通常是一个64位的有符号整数long int 或 long long int。 因此具体的 off_t 实际类型可能会根据编译器和操作系统的不同而有所变化。但一般来说 它应该是一个能够表示大文件偏移量的整数类型。*/lseek() 函数接受三个参数文件描述符 fd、偏移量 offset 和起始位置 whence。 fd 是要进行操作的文件描述符。offset 是一个整数值表示要相对于起始位置移动的字节数。正值将向后移动负值将向前移动。whence 指定了起始位置有以下几种选项 SEEK_SET从文件开头开始计算偏移量。SEEK_CUR从当前位置开始计算偏移量。SEEK_END从文件末尾开始计算偏移量。 以下是 lseek() 函数的使用方法示例 #include unistd.h #include fcntl.hint fd open(filename.txt, O_RDONLY); if (fd ! -1) {off_t new_offset lseek(fd, 0, SEEK_END);if (new_offset -1) {// 获取文件偏移量失败} else {// 成功获取文件偏移量// 可以根据需要进行读取或写入操作}close(fd); } else {// 文件打开失败 }上述示例代码首先使用 open() 函数以只读模式打开文件并获取到文件描述符 fd。然后调用 lseek() 函数将偏移量设置为相对于文件末尾的位置通过 SEEK_END 参数。如果 lseek() 函数返回值为-1则表示设置文件偏移量失败。否则可以根据需要进行读取或写入操作。 请注意lseek() 函数常用于随机访问文件允许在文件中任意位置进行读取和写入操作。它适用于支持定位操作的设备如磁盘文件。 open函数返回值 在认识返回值之前先来认识一下两个概念: 系统调用 和 库函数 当编写程序时我们可以使用系统调用和库函数来访问操作系统提供的功能。这两个概念有一些区别 系统调用System Call 系统调用是应用程序与操作系统之间进行交互的接口。它允许应用程序请求操作系统执行某些特权操作或获取底层资源。系统调用提供了对操作系统核心功能的直接访问。 在系统调用中应用程序通过特定的指令通常是软件中断将控制权转移给操作系统内核并传递参数以指示所需的操作。操作系统内核处理该请求并返回结果给应用程序。 系统调用涉及低级别的操作例如文件管理、进程管理、网络通信等。由于系统调用需要切换到内核模式因此执行系统调用可能比执行用户空间代码更耗时。一般而言系统调用提供了较为底层的操作接口。 库函数Library Function 库函数是预先编写好的可重用代码块封装了常见的操作和算法。它们位于动态链接库shared library或静态库static library中供应用程序调用。 库函数通常提供高级别的抽象和简化的接口使得开发人员能够更方便地使用各种功能。库函数隐藏了底层实现细节提供了更高层次的抽象使得开发人员可以更专注于应用程序逻辑。 库函数可以涉及各种领域如字符串处理、数学运算、图形界面等。它们是在用户空间中执行的无需切换到内核模式。由于库函数通常封装了一些常见操作因此其执行速度可能比系统调用更快。 总结来说系统调用是应用程序与操作系统之间进行交互的接口提供对底层资源和功能的直接访问而库函数是预先编写好的可重用代码块提供了高级别的抽象和简化的接口使得开发人员能够更方便地使用各种功能。 需要注意的是库函数有时候也会调用底层的系统调用来完成特定任务。这样做的目的是利用系统调用提供的底层功能并通过库函数的封装使其更易于使用。 上面的 fopen fclose fread fwrite 都是C标准库当中的函数我们称之为库函数libc。 而 open close read write lseek 都属于系统提供的接口称之为系统调用接口 回忆一下我们讲操作系统概念时 画的一张图 系统调用接口和库函数的关系一目了然。 文件描述符fd 文件描述符File Descriptor, 简称FD是一个在Unix、Linux以及其他类Unix操作系统中广泛使用的概念。它是一个非常小的非负整数由操作系统用来唯一标识一个打开的文件。当程序打开一个现有文件或创建一个新文件时操作系统会创建一个文件描述符来代表该文件并将其返回给程序。 文件描述符主要用于文件I/O操作例如读取、写入、关闭文件等。这是一种底层的抽象使得操作系统可以通过统一的接口操作各种类型的I/O资源如普通文件、目录、套接字socket、管道pipe等。 在标准POSIX定义中标准输入stdin、标准输出stdout和标准错误stderr分别有三个预定义的文件描述符 0标准输入1标准输出2标准错误 程序可以使用这些文件描述符进行基本的输入输出操作。例如在C语言中可以使用标准库函数如read和write来通过文件描述符进行读写操作。 以下是一些用于管理文件描述符的常用系统调用 open打开或创建一个文件并返回一个新的文件描述符。close关闭一个文件描述符释放它所占用的资源。read从一个文件描述符指向的文件中读取数据。write向一个文件描述符指向的文件写入数据。dup 和 dup2复制一个文件描述符可以用于重定向输入输出。 在某些情况下如并发服务器的设计中文件描述符的管理显得尤为重要因为需要高效地处理大量打开的文件。由于文件描述符是有限的资源不正确的管理可能导致资源泄露问题比如“文件描述符耗尽”。因此在编写涉及文件操作的程序时确保在不再需要文件描述符时关闭它们是很重要的。 0 1 2 Linux进程默认情况下会有3个缺省打开的文件描述符分别是标准输入0 标准输出1 标准错误2. 0,1,2对应的物理设备一般是键盘显示器显示器 所以输入输出还可以采用如下方式 #include stdio.h #include unistd.h #includesys/types.h #includesys/stat.h #includefcntl.h #includestring.hint main() {char buff[1024];ssize_t s read(0,buff,sizeof(buff));if(s0){buff[s]0;write(1,buff,strlen(buff));write(2,buff,strlen(buff));}return 0; }运行结果为输入一行字会在显示器上全打印出来。 底层内核实现图如下 而现在知道文件描述符就是从0开始的小整数。当我们打开文件时操作系统在内存中要创建相应的数据结构来 描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用所以必须让进 程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组每个元素都是一个指向打开文件的指针所以本质上文件描述符就是该数组的下标。所以只要拿着文件描述符就可以找到对应的文件。 文件描述符的分配规则 直接看代码 #includestdio.h #includesys/types.h #includesys/stat.h #includefcntl.h #includeunistd.hint main() {int fd open(myfile.txt,O_RDONLY|O_CREAT);if(fd0){perror(open fail);return 1;}printf(fd: %d\n,fd);close(fd);return 0; }输出发现是 fd: 3 此时关闭0或者2再看 #includestdio.h #includesys/types.h #includesys/stat.h #includefcntl.h #includeunistd.hint main() {close(0);//close(2);int fd open(myfile.txt, O_RDONLY);if(fd 0){perror(open);return 1;}printf(fd: %d\n, fd);close(fd);return 0; }发现是结果是 fd: 0 或者 fd 2 可见文件描述符的分配规则在files_struct数组当中找到当前没有被使用的 最小的一个下标作为新的文件描述符。 重定向 那如果关闭1呢看代码 #includestdio.h #includesys/types.h #includesys/stat.h #includefcntl.h #includeunistd.h #includestdlib.hint main() {close(1);int fd open(myfile.txt,O_WRONLY|O_CREAT,0644);if(fd0){perror(open fail);return 1;}printf(fd:%d\n,fd);fflush(stdout);close(fd);exit(0); }此时我们发现本来应该输出到显示器上的内容输出到了文件 myfile 当中其中fd1。这种现象叫做输出 重定向。常见的重定向有:, , 那重定向的本质是什么呢见下图 使用 dup2 系统调用 dup2 是 UNIX 和类 UNIX 系统如 Linux中的一个系统调用它用于复制文件描述符。给定两个文件描述符dup2 会使第二个文件描述符成为第一个文件描述符的副本如果必要的话会关闭第二个文件描述符。这个操作常常用于重定向标准输入、输出和错误流。 dup2 函数的原型定义在 unistd.h 头文件中其原型如下 #include unistd.hint dup2(int oldfd, int newfd);参数 oldfd 是已打开的文件描述符的副本。newfd 是你想要 oldfd 复制到的文件描述符编号。 如果 newfd 已经打开dup2 会先关闭它然后再复制 oldfd。如果 oldfd 是无效的文件描述符dup2 不会关闭 newfd并且会返回错误。 返回值 成功时返回新的文件描述符即 newfd。如果出现错误返回 -1 并设置 errno 来表示错误类型。 使用示例 假设你想要将程序的标准输出重定向到一个文件你可以使用 open 系统调用打开或创建一个文件获取其文件描述符然后使用 dup2 将标准输出复制到这个文件描述符上。 #include unistd.h #include fcntl.h #include stdio.h #include stdlib.hint main() {// 打开一个文件用于写入。如果不存在就创建它权限设置为 0644int fd open(output.txt, O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd -1) {perror(open);exit(EXIT_FAILURE);}// 复制文件描述符 fd 到标准输出stdoutif (dup2(fd, STDOUT_FILENO) -1) {perror(dup2);exit(EXIT_FAILURE);}// 现在标准输出已经重定向到 output.txtprintf(这将会写入到 output.txt\n);// 关闭原始文件描述符 fdif (close(fd) -1) {perror(close);exit(EXIT_FAILURE);}// 继续程序的其他部分...return 0; }在上面的代码中STDOUT_FILENO 是标准输出的文件描述符编号通常是 1。open 调用用于打开或创建文件 output.txt。然后 dup2 调用用于将 stdout 重定向到这个文件。之后所有写入 stdout 的内容都会出现在 output.txt 文件中。最后通过调用 close 来关闭原始的文件描述符 fd。 FILE 因为IO相关函数与系统调用接口对应并且库函数封装系统调用所以本质上访问文件都是通过fd访问的。所以C库当中的FILE结构体内部必定封装了fd。 来段代码在研究一下 #include stdio.h #include string.h #includeunistd.h#includestdlib.hint main() {const char *msg0hello printf\n;const char *msg1hello fwrite\n;const char *msg2hello write\n;printf(%s, msg0);fwrite(msg1, strlen(msg0), 1, stdout);write(1, msg2, strlen(msg2));fork();return 0; }运行出结果 但如果对进程实现输出重定向呢 ./hello file 我们发现结果变成了 我们发现 printf 和 fwrite 库函数都输出了2次而 write 只输出了一次系统调用。为什么呢肯定和fork有关 这个现象的原因在于printf和fwrite是库函数它们使用了缓冲IO而write是系统调用使用了非缓冲IO。 在C语言中库函数printf和fwrite在输出时会先将数据保存到缓冲区只有在以下几种情况下才会将缓冲区的内容输出 缓冲区满。遇见’\n’。 而系统调用write则会直接输出不经过缓冲区。 当你使用fork创建子进程时子进程会复制父进程的所有资源包括缓冲区。因此如果在fork之前printf和fwrite的输出还在缓冲区中没有被输出那么在子进程中这些输出会被再次输出因此你看到printf和fwrite输出了两次。而write因为是直接输出所以只输出了一次。 如果你希望printf和fwrite在fork之前就输出可以在它们之后调用fflush(stdout)来强制刷新缓冲区。这样fork时就不会复制还未输出的数据从而避免重复输出。希望这个解释能帮到你 综上 printf fwrite 库函数会自带缓冲区而 write 系统调用没有带缓冲区。另外我们这里所说的缓冲区都是用户级缓冲区。其实为了提升整机性能OS也会提供相关内核级缓冲区不过不再我们讨论范围之内。那这个缓冲区谁提供呢 printf fwrite 是库函数 write 是系统调用库函数在系统调用的“上层” 是对系统调用的“封装”但是 write 没有缓冲区而 printf fwrite 有足以说明该缓冲区是二次加上的又因为是C所以由C标准库提供。 如果有兴趣可以看看FILE结构体: typedef struct _IO_FILE FILE; 在/usr/include/stdio.hstruct _IO_FILE {int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ #define _IO_file_flags _flags//缓冲区相关/* The following pointers correspond to the C streambuf protocol. *//* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */char* _IO_read_ptr; /* Current read pointer */char* _IO_read_end; /* End of get area. */char* _IO_read_base; /* Start of putbackget area. */char* _IO_write_base; /* Start of put area. */char* _IO_write_ptr; /* Current put pointer. */char* _IO_write_end; /* End of put area. */char* _IO_buf_base; /* Start of reserve area. */char* _IO_buf_end; /* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base; /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno; //封装的文件描述符 #if 0int _blksize; #elseint _flags2; #endif_IO_off_t _old_offset; /* This used to be _offset but its too small. */ #define __HAVE_COLUMN /* temporary *//* 1column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];/* char* _save_gptr; char* _save_egptr; */_IO_lock_t *_lock; #ifdef _IO_USE_OLD_IO_FILE };_IO_FILE是Linux系统中用于描述文件的结构称为文件流。在程序执行时fread、fwrite等标准函数需要文件流指针来指引去调用虚表函数。特殊地fopen等函数会进行创建并分配在堆中。 _IO_FILE结构体中的各个字段主要包括 _flags高位是_IO_MAGIC其余是标志位。_IO_read_ptr、_IO_read_end、_IO_read_base这些字段与读缓冲区有关。_IO_write_base、_IO_write_ptr、_IO_write_end这些字段与写缓冲区有关。_IO_buf_base、_IO_buf_end这些字段与备用区有关。_IO_save_base、_IO_backup_base、_IO_save_end这些字段用于支持备份和撤销。_markers标记。_chain指向下一个_IO_FILE结构。_fileno封装的文件描述符。 理解文件系统 我们使用ls -l的时候看到的除了看到文件名还看到了文件元数据。 每行包含8列 模式 硬链接数 文件所有者 文件所属组 大小 最后修改时间 文件名 ls -l读取存储在磁盘上的文件信息然后显示出来 其实这个信息除了通过这种方式来读取还有一个stat命令能够看到更多信息。 上面的执行结果有几个信息需要解释清楚 inode为了能解释清楚inode我们先简单了解一下文件系统 Linux ext2文件系统上图为磁盘文件系统图内核内存映像肯定有所不同磁盘是典型的块设备硬盘分区被 划分为一个个的block。一个block的大小是由格式化的时候确定的并且不可以更改。例如mke2fs的-b选项可以设 定block大小为1024、2048或4096字节。而上图中启动块Boot Block的大小是确定的 Block Groupext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。政府管理各区的例子 超级块Super Block存放文件系统本身的结构信息。记录的信息主要有bolck 和 inode的总量未使用的block和inode的数量一个block和inode的大小最近一次挂载的时间最近一次写入数据的时间最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏可以说整个文件系统结构就被破坏了 GDTGroup Descriptor Table块组描述符描述块组属性信息有兴趣的同学可以在了解一下 块位图Block BitmapBlock Bitmap中记录着Data Block中哪个数据块已经被占用哪个数据块没有被占用 inode位图inode Bitmap每个bit表示一个inode是否空闲可用。 i节点表:存放文件属性 如 文件大小所有者最近修改时间等 数据区存放文件内容 将属性和数据分开存放的想法看起来很简单但实际上是如何工作的呢我们通过touch一个新文件来看看如何工 作。 为了说明问题我们将上图简化 创建一个新文件主要有一下4个操作 存储属性 内核先找到一个空闲的i节点这里是263466。内核把文件信息记录到其中。存储数据 该文件需要存储在三个磁盘块内核找到了三个空闲块300,500800。将内核缓冲区的第一块数据 复制到300下一块复制到500以此类推。记录分配情况 文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。添加文件名到目录 新的文件名abc。linux如何在当前的目录中记录这个文件内核将入口263466abc添加到目录文件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。 理解硬链接 我们看到真正找到磁盘上文件的并不是文件名而是inode。 其实在linux中可以让多个文件名对应于同一个 inode。 这是Linux系统中创建硬链接的命令。让我们逐一解析这些命令 touch abc这个命令创建了一个名为abc的新文件。ln abc def这个命令创建了一个名为def的硬链接它链接到了文件abc。这意味着abc和def实际上是同一个文件只是名字不同。ls -li这个命令列出了当前目录下的文件以及它们的inode号。在这个例子中abc和def有相同的inode号1580155这表明它们是同一个文件的硬链接。 总的来说这些命令创建了一个新文件abc然后为这个文件创建了一个硬链接def。这两个名字实际上指向的是同一个文件。 软链接 硬链接是通过inode引用另外一个文件软链接是通过名字引用另外一个文件在shell中的做法。 在shell中创建软链接的命令是ln -s¹²。以下是具体的指令 创建软链接 ln -s 源文件或目录 软链接文件或目录在上述指令中源文件或目录和软链接文件或目录需要替换为实际的源文件或目录的路径以及你想要创建的软链接的路径¹²。 例如如果你想为/bin/less创建一个软链接/usr/local/bin/less你可以使用以下命令² ln -s /bin/less /usr/local/bin/less这样当你访问/usr/local/bin/less时实际上访问的是/bin/less²。 acm 下面解释一下文件的三个时间 Access 最后访问时间 Modify 文件内容最后修改时间 Change 属性最后修改时间 动态库和静态库 静态库与动态库 静态库.a程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库动态库.so程序在运行的时候才去链接动态库的代码多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表而不是外部函数所在目标文件的整个机器码在可执行文件开始运行以前外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中这个过程称为动态链接dynamic linking动态库可以在多个程序间共享所以动态链接使得可执行文件更小节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用节省了内存和磁盘空间。 测试程序 /add.h/ #pragma once int add(int x,int y); /add.c/ #includeadd.hint add(int x,int y) {return xy; } /sub.h/ #pragma once int sub(int x,int y); /sub.c/ #includesub.hint sub(int x,int y) {return x-y; } ///main.c #includestab.h #includeadd.h #includesub.hint main() {int c add(3,4);printf(34%d\n,c);int d sub(5,2);printf(5-2%d\n,d);return 0; }生成静态库 要生成静态库你需要将 add.c 和 sub.c 这两个源文件编译成目标文件然后将这些目标文件打包成静态库文件。下面是生成静态库的步骤 首先编译 add.c 和 sub.c 这两个源文件为目标文件。使用以下命令分别编译它们 gcc -c add.c -o add.o gcc -c sub.c -o sub.o接下来将这两个目标文件打包成静态库文件。使用以下命令将目标文件打包成 libmymath.a 静态库文件 ar rcs libmymath.a add.o sub.o这将创建一个名为 libmymath.a 的静态库文件其中包含了 add.o 和 sub.o 这两个目标文件的内容。 现在你可以在 main.c 中使用这个静态库文件。确保 main.c 文件中包含了正确的头文件引用并使用以下命令编译 main.c 并链接静态库文件 gcc main.c -L. -lmymath -o myprogram这将生成一个名为 myprogram 的可执行文件其中包含了 main.c 中的代码并链接了 libmymath.a 静态库文件。 请确保在编译和链接过程中所有的文件路径和文件名都正确无误。如果一切顺利你应该能够成功生成静态库和可执行文件。 生成动态库 要生成动态库你可以按照以下步骤进行操作 首先编译 add.c 和 sub.c 文件生成对应的目标文件。使用以下命令 gcc -c add.c -o add.o gcc -c sub.c -o sub.o这将分别生成 add.o 和 sub.o 两个目标文件。 接下来将目标文件链接为一个动态库。使用以下命令 gcc -shared add.o sub.o -o libmymath.so这将把 add.o 和 sub.o 链接为一个名为 libmymath.so 的动态库。 生成动态库后你可以在 main.c 中使用该库。确保在 main.c 中包含正确的头文件引用 #include stdio.h #include add.h #include sub.h最后编译 main.c 并链接动态库。使用以下命令 gcc main.c -L. -lmymath -o myprograms这将链接 main.c 并指定动态库的路径和名称。 现在你可以运行 myprogram 可执行文件它将使用动态库中的函数。 请注意生成动态库的命令和生成静态库的命令略有不同。动态库使用 -shared 选项进行链接而静态库使用 ar 命令进行打包。确保在编译和链接时使用正确的选项和命令。
http://www.yayakq.cn/news/1151/

相关文章:

  • tiktok官方网站入口小网站怎么建设
  • 局强化网站建设和管理如何进入网站管理页面
  • 彩票网站自己可以做吗杭州百度开户
  • 自己的电脑建网站WordPress做头部的插件
  • 怎么做属于自己的售卡网站网站模版防被偷
  • 深圳手机网站模板天眼通查公司查询
  • 郑州前端开发培训机构企业网站设计有名 乐云seo
  • 清风算法受影响的网站有网络但浏览器打不开网页
  • 云南网站建设哪家权威企业宣传片文案大全
  • 给自己做的网站换首页深圳设计总院
  • 保定市城乡建设局官方网站一个工厂做网站有什么好处
  • 网站建设发言找装修
  • 电子商务网站建设的工具做网站怎么带流量
  • jsp网站开发步骤百度云图片转wordpress
  • 平凉市网站建设制作小程序游戏排行榜2023
  • 朔州网站建设电话微信商城与网站一体
  • 查看网站百度排名广州百度提升优化
  • 软件开发工程师机构竞价排名和seo的区别
  • 一女被多男做的视频网站90设计网页版
  • 大连网站前端制作公司网上做家教兼职哪个网站
  • 做网站换域名珠海溢动网络科技有限公司
  • 营销网站建设的价格wordpress 不带主题显示
  • 网站一般用什么语言写ios开发者账号多少钱一年
  • 哪些企业需要网站建设的公司网站功能性建设有哪些
  • 个人网站网页设计模板临沂设计网站的公司
  • 工信和信息化网站备案系统广州网站开发十度网络最好
  • 英语门户网站织梦源码简洁轻便的wordpress主题
  • 网站开发项目个人总结做的网站怎么发布到网上
  • 网站栏目下拉菜单南昌seo站内优化
  • 南通市网站建设浑南区建设局网站