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

三亚建设工程信息网站南充微网站建设

三亚建设工程信息网站,南充微网站建设,综合门户网站建设,建设银行深圳天健世纪支行网站目录 ​编辑 一、C语言文件接口#xff08;库函数#xff09; hello.c写文件 hello.c读文件 输出信息到显示器 stdin stdout stderr 二、系统文件I/O#xff08;系统调用#xff09; hello.c 写文件#xff1a; hello.c读文件 接口介绍 open open… 目录 ​编辑 一、C语言文件接口库函数 hello.c写文件 hello.c读文件  输出信息到显示器 stdin stdout stderr 二、系统文件I/O系统调用 hello.c 写文件 hello.c读文件 接口介绍 open open函数返回值 三、文件描述符fd 文件描述符的分配规则 使用 dup2 系统调用 重定向 四、FILE 户级缓冲区 五、理解文件系统 文件文件内容文件属性 inode(类似于进程pid) 六、软链接和硬链接  硬链接  软链接 七、linux中文件系统内核图简略​编辑 八、动态库和静态库 生成静态库shell指令  库搜索路径 生成动态库 使用动态库 运行动态库 库文件名称和引入库的名称 一、C语言文件接口库函数 写接口功能 读接口 printf()默认输出到显示器scanf()默认从键盘读fprintf()写入格式类上输出到指定文件中指定需要通过C语言提供的流一种对文件进行描述的数据结构指针 FILE *fscanf()写入格式类上写入到指定文件中通过流fread()指定地址字节数数目写入到指定文件中通过流指定文件fseek可以设置流指向文件中的位置来改变写入文件的起始地址fwrite()指定文件和字节数以及数目写入到程序提供的地址中文件中的地址默认在开头fseek可以设置流指向文件中的位置来改变拷贝文件的起始地址 hello.c写文件 #include stdio.h#include string.hint 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);return 0;} hello.c读文件  #include stdio.h#include string.hint main(){FILE *fp fopen(myfile, r);if(!fp){printf(fopen error!\n);}char buf[1024];const char *msg hello bit!\n;while(1){//注意返回值和参数此处有坑仔细查看man手册关于该函数的说明ssize_t s fread(buf, 1, strlen(msg), fp);if(s 0){buf[s] 0;printf(%s, buf);}if(feof(fp)){break;}}fclose(fp);return 0;} 输出信息到显示器 #include stdio.h#include string.hint 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返回值类型文件指针 打开文件的方式 r Open text file for reading. The stream is positioned at the beginning of the file.r Open for reading and writing. The stream is positioned at the beginning of the file.w Truncate(缩短) file to zero length or create text file for writing. The stream is positioned at the beginning of the file.w Open for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file.a Open for appending (writing at end of file). The file is created if it does not exist. The stream is positioned at the end of the file.a Open for reading and appending (writing at end of file). The file is created if it does not exist. The initial file position for reading is at the beginning of the file, but output is always appended to the end of the file. 如上是我们之前学的文件相关操作。还有fseek ftell rewind的函数在C部分已经有所涉猎。请百度。 二、系统文件I/O系统调用 操作文件除了上述C接口当然C也有接口其他语言也有我们还可以采用系统接口来进行文件访问 先来直接以代码的形式实现和上面一模一样的代码 注意以下是用linux系统进行演示的在windows下系统调用可能不一样但是之前的c语言代码可以多个平台编译后运行c语言库中对各个系统的都有各自的编译器c语言的标准库中封装了各个系统的系统调用通过编译时的处理来匹配各自系统的系统调用从而实现c语言的跨平台性。 hello.c 写文件 #include stdio.h#include sys/types.h#include sys/stat.h#include fcntl.h#include unistd.h#include string.hint 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.hint 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;} 接口介绍 open linux 手册查看命令man open #include stdio.h#include sys/types.h#include sys/stat.h#include fcntl.h#include unistd.h#include string.hint 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;}#include sys/types.h#include sys/stat.h#include fcntl.hint open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);pathname: 要打开或创建的目标文件 flags: 打开文件时可以传入多个参数选项用下面的一个或者多个常量进行“或”运算构成flags。 参数:O_RDONLY: 只读打开O_WRONLY: 只写打开O_RDWR : 读写打开这三个常量必须指定一个且只能指定一个O_CREAT : 若文件不存在则创建它。需要使用mode选项来指明新文件的访问权限O_APPEND: 追加写 返回值成功新打开的文件描述符失败-1mode_t理解直接 man 手册比什么都清楚。命令man mode_t open 函数具体使用哪个和具体应用场景相关如目标文件不存在需要open创建则第三个参数表示创建文件的默认权限,否则使用两个参数的open。 write read close lseek ,类比C文件相关接口。 open函数返回值 在认识返回值之前先来认识一下两个概念: 系统调用 和库函数上面的 fopen fclose fread fwrite 都是C标准库当中的函数我们称之为库函数libc。而open fread close read write lseek 都属于系统提供的接口称之为系统调用接口 系统调用接口和库函数的关系一目了然。 所以可以认为f#系列的函数都是对系统调用的封装方便二次开发。 三、文件描述符fd 通过对open函数的学习我们知道了文件描述符就是一个小整数 0 1 2 Linux进程默认情况下会有3个缺省打开的文件描述符分别是标准输入0 标准输出1 标准错误2.0,1,2对应的物理设备一般是键盘显示器显示器所以输入输出还可以采用如下方式 #include stdio.h#include sys/types.h#include sys/stat.h#include fcntl.h#include string.hint main(){char buf[1024];ssize_t s read(0, buf, sizeof(buf));if(s 0){buf[s] 0;write(1, buf, strlen(buf));write(2, buf, strlen(buf));}return 0;} linux内核结构图        而现在知道文件描述符就是从0开始的小整数。当我们打开文件时操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用所以必须让进程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组每个元素都是一个指向打开文件的指针所以本质上文件描述符就是该数组的下标。所以只要拿着文件 描述符就可以找到对应的文件。 文件描述符的分配规则 直接看代码 #include stdio.h#include sys/types.h#include sys/stat.h#include fcntl.hint main(){int fd open(myfile, O_RDONLY);if(fd 0){perror(open);return 1;}printf(fd: %d\n, fd);close(fd);return 0;} 输出发现是 fd: 3 关闭0或者2再次实验 #include stdio.h#include sys/types.h#include sys/stat.h#include fcntl.h#include stdlib.hint main(){close(1);int fd open(myfile, O_WRONLY|O_CREAT, 00644);if(fd 0){perror(open);return 1;}printf(fd: %d\n, fd);fflush(stdout);close(fd);exit(0);} 此时我们发现本来应该输出到显示器上的内容输出到了文件myfile当中其中fd1。这种现象叫做输出 重定向。常见的重定向有:, , 那重定向的本质是什么呢 使用 dup2 系统调用 重定向 函数声明和头文件 #include unistd.hint dup2(int oldfd, int newfd);函数功能使文件描述符newfd的被文件描述符oldfd覆盖本质上是oldfd下标的指针指向newfd下标的指针所指向的用于描述文件的结构体file。 示例代码  #include stdio.h#include unistd.h#include fcntl.hint main() {int fd open(./log, O_CREAT | O_RDWR);if (fd 0) {perror(open);return 1;}close(1);dup2(fd, 1);for (;;) {char buf[1024] {0};ssize_t read_size read(0, buf, sizeof(buf) - 1);if (read_size 0) {perror(read);break;}printf(%s, buf);fflush(stdout);}return 0;} printf是C库当中的IO函数一般往stdout中输出但是stdout底层访问文件的时候找的还是fd:1, 但此时fd:1 下标所表示内容已经变成了myfile的地址不再是显示器文件的地址所以输出的任何消息都会往文件中写 入进而完成输出重定向。那追加和输入重定向如何完成呢请同学们自行研究。 四、FILE 因为IO相关函数与系统调用接口对应并且库函数封装系统调用所以本质上访问文件都是通过fd访问的。所以C库当中的FILE结构体内部必定封装了fd。 来段代码在研究一下 if (pid 0) {do_redirect(buff);argv do_parse(buff);if (argv[0] NULL) {exit(-1);}execvp(argv[0], argv);}else {waitpid(pid, NULL, 0);}return 0;}int main(int argc, char *argv[]){while(1) {if (do_face() 0)continue;do_exec(command);}return 0;}#include stdio.h#include string.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 printfhello fwritehello write 但如果对进程实现输出重定向呢 ./hello file 我们发现结果变成了 hello writehello printfhello fwritehello printfhello fwrite 我们发现printf 和 fwrite 库函数都输出了2次write只输出了一次系统调用。为什么呢肯定和而fork有关 户级缓冲区 一般C库函数写入文件时是全缓冲的而写入显示器是行缓冲。printf fwrite 库函数会自带缓冲区属于每个进程的缓冲区进度条例子就可以说明当发生重定向到普通文件时数据的缓冲方式由行缓冲变成了全缓冲。而我们放在缓冲区中的数据就不会被立即刷新甚至fork之后但是进程退出之后会统一刷新写入文件当中。但是fork的时候父子数据会发生写时拷贝所以当你父进程准备刷新的时候子进程也就有了同样的一份数据随即产生两份数据。write 没有变化说明没有所谓的缓冲。 综上 printf fwrite 库函数会自带缓冲区而 write 系统调用没有带缓冲区。另外我们这里所说的缓冲区 都是用户级缓冲区。其实为了提升整机性能OS也会提供相关内核级缓冲区不过不再我们讨论范围之内。 那这个缓冲区谁提供呢         printf fwrite 是库函数 write 是系统调用库函数在系统调用的“上层” 是对系统调用的“封装”但是 write 没有缓冲区printffwrite有足以说明该缓冲区是二次加上的又因为是而C所以由C标准库提供。  如果有兴趣可以看看FILE结构体: typedef struct _IO_FILE FILE; 在/usr/include/stdio.h 五、理解文件系统 文件文件内容文件属性 我们使用ls -l的时候看到的除了看到文件名还看到了文件的属性。 [rootlocalhost linux]# ls -l total 12 -rwxr-xr-x. 1 root root 7438 9月 13 14:56 a.out -rw-r--r--. 1 root root 654 9月 13 14:56 test.c 每行包含7列模式    硬链接数    文件所有者    文件所属组    大小    最后修改时间    文件名 ls -l读取存储在磁盘上的文件信息然后显示出来 其实这个信息除了通过这种方式来读取还有一个stat命令能够看到更多信息  上面的执行结果有几个信息需要解释清楚 inode(类似于进程pid) 为了能解释清楚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的信息被破坏可以说整个文件系统结构就被破坏了不是每个块组都有superBlock每隔几个会存在一个Super Block。GDTGroup Descriptor Table块组描述符描述块组属性信息有兴趣的同学可以在了解一下块位图Block BitmapBlock Bitmap中记录着Data Block中哪个数据块已经被占用哪个数据块没 有被占用inode位图inode Bitmap每个bit表示一个inode是否空闲可用。i节点表(inode Table):存放文件属性 如 文件大小所有者最近修改时间等可以理解为文件属性的存放地址数据区存放文件内容 将属性和数据分开存放的想法看起来很简单但实际上是如何工作的呢我们通过touch一个新文件来看看如何工作。 [rootlocalhost linux]# touch abc[rootlocalhost linux]# ls -i abc263466 abc 为了说明问题我们将上图简化 创建一个新文件主要有一下4个操作 1. 存储属性内核先找到一个空闲的i节点这里是263466。内核把文件信息记录到其中。 2. 存储数据该文件需要存储在三个磁盘块内核找到了三个空闲块300,500800。将内核缓冲区的第一块数据 复制到300下一块复制到500以此类推。 3. 记录分配情况 文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。 4. 添加文件名到目录 新的文件名abc。linux如何在当前的目录中记录这个文件内核将入口263466abc添加到目录文 件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。 六、软链接和硬链接  硬链接  理解硬链接  我们看到真正找到磁盘上文件的并不是文件名而是inode利用inode找到文件。 其实在linux中可以让多个文件名对应于同一个 inode。 创建一个硬链接实际内存中就是在目录下添加一个文件名和inode的映射。ps目录文件的内容包含文件名和inode的映射。这样才能通过输入的指令中包含的文件名找到文件inode对文件进行各自操作。 [rootlocalhost linux]# touch abc [rootlocalhost linux]# ln abc def [rootlocalhost linux]# ls -1i abc def 263466 abc 263466 def abc和def的链接状态完全相同他们被称为指向文件的硬链接。 内核记录了这个连接数inode 263466 的硬连接数为2。 我们在删除文件时干了两件事情 1.在目录中将对应的记录删除 2.将硬连接数-1如果为0则将对应 的磁盘释放 实例:可以发现除了文件名不同其他都相同。 软链接 硬链接是通过inode引用另外一个文件软链接是通过文件内容引用另外一个文件在shell中的做法。可以理解成快捷方式存储的是另一文件的地址 263563 -rw-r--r--. 2 root root 0 9月 15 17:45 abc261678 lrwxrwxrwx. 1 root root 3 9月 15 17:53 abc.s - abc263563 -rw-r--r--. 2 root root 0 9月 15 17:45 def acm 下面解释一下文件的三个时间 Access 最后访问时间Modify 文件内容最后修改时间Change 属性最后修改时间  七、linux中文件系统内核图简略 八、动态库和静态库 静态库.a程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库动态库.so程序在运行的时候才去链接动态库的代码多个程序共享使用库的代码。一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表而不是外部函数所在目标文件的整个机器码在可执行文件开始运行以前外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中这个过程称为动态链接dynamic linking动态库可以在多个程序间共享所以动态链接使得可执行文件更小节省了磁盘空间。操作系统采用虚 拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用节省了内存和磁盘空间。 测试程序 /add.h/#ifndef __ADD_H__#define __ADD_H__ int add(int a, int b); #endif // __ADD_H__/add.c/#include add.hint add(int a, int b){return a b;}/sub.h/#ifndef __SUB_H__#define __SUB_H__ int sub(int a, int b); #endif // __SUB_H__/add.c/#include add.hint sub(int a, int b){return a - b;}///main.c#include stdio.h#include add.h#include sub.hint main( void ){int a 10;int b 20;printf(add(10, 20)%d\n, a, b, add(a, b));a 100;b 20;printf(sub(%d,%d)%d\n, a, b, sub(a, b));} 生成静态库shell指令  [rootlocalhost linux]# lsadd.c add.h main.c sub.c sub.h[rootlocalhost linux]# gcc -c add.c -o add.o[rootlocalhost linux]# gcc -c sub.c -o sub.o生成静态库 [rootlocalhost linux]# ar -rc libmymath.a add.o sub.o ar是gnu归档工具rc表示(replace and create)查看静态库中的目录列表 [rootlocalhost linux]# ar -tv libmymath.a rw-r--r-- 0/0 1240 Sep 15 16:53 2017 add.orw-r--r-- 0/0 1240 Sep 15 16:53 2017 sub.ot:列出静态库中的文件 v:verbose 详细信息[rootlocalhost linux]# gcc main.c -L. -lmymath-L 指定库路径-l 指定库名 测试目标文件生成后静态库删掉程序照样可以运行。 库搜索路径 从左到右搜索-L指定的目录。 由环境变量指定的目录 LIBRARY_PATH 由系统指定的目录 /usr/lib       /usr/local/lib 生成动态库 shared: 表示生成共享库格式fPIC产生位置无关码(position independent code)库名规则libxxx.so 示例 [rootlocalhost linux]# gcc -fPIC -c sub.c add.c [rootlocalhost linux]# gcc -shared -o libmymath.so *.o [rootlocalhost linux]# ls add.c add.h add.o libmymath.so main.c sub.c sub.h sub.o 使用动态库 编译选项 l链接动态库只要库名即可(去掉lib以及版本号) L链接库所在的路径. 示例 gcc main.o -o main –L. -lhello 运行动态库 1、拷贝.so文件到系统共享库路径下, 一般指/usr/lib 2、更改LD_LIBRARY_PATH [rootlocalhost linux]# export LD_LIBRARY_PATH.[rootlocalhost linux]# gcc main.c -lmymath[rootlocalhost linux]# ./a.outadd(10, 20)30sub(100, 20)8 3、ldconfig 配置/etc/ld.so.conf.d/ldconfig更新 [rootlocalhost linux]# cat /etc/ld.so.conf.d/bit.conf /root/tools/linux[rootlocalhost linux]# ldconfig 使用外部库 系统中其实有很多库它们通常由一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显示情况 的函数ncurses库 #include math.h#include stdio.hint main(void){double x pow(2.0, 3.0);printf(The cubed is %f\n, x);return 0;}gcc -Wall calc.c -o calc -lm -lm表示要链接libm.so或者libm.a库文件 库文件名称和引入库的名称 如libc.so - c库去掉前缀lib去掉后缀.so,.a
http://www.w-s-a.com/news/767062/

相关文章:

  • 合肥建设工会网站芜湖做网站建设公司
  • 玉林市住房和城乡建设局网站网站开发百灵鸟
  • 网站怎么做双机房切换建设部网站2015年第158号
  • 郑州服务设计公司网站色块的网站
  • 网站设计所用到的技术做网站添加mp3
  • 凡科做的微网站怎样连接公众号seo李守洪排名大师
  • 温州网站开发网站的制作东莞寮步伟易达电子厂
  • 北京网站设计制作关键词优化微信小程序开发推广网站建设优化规划书
  • 杭州临平网站建设开发公司将购房款划给总公司的法律责任
  • 广东外贸网站推广分类wordpress
  • 聚美优品网站建设方案商城和营销型网站建设
  • 比较著名的seo网站如何建设网站?
  • 如何做商业网站最火wordpress主题
  • 建设网站需要哪些软硬件条件wordpress文章页标题优化
  • 网站建设功能需求文档wordpress 1g1核1m
  • 学做窗帘要下载哪个网站用户反馈数据分析软件园
  • 宁晋网站建设多少钱产品宣传推广方式有哪些
  • delphi做网站阿里巴巴官网首页登录入口
  • 游戏网站怎么建设新建wordpress模板
  • 网络服务器是指兰州网站seo诊断
  • 怎样做投资理财网站godaddy上传网站
  • 网站建设深圳哪家好世界500强企业招聘网站
  • 如何减少网站建设中的错误温州网站公司哪家好
  • 宜章网站建设北京定制公交网站
  • 怎么让谷歌收录我的网站郑州网站建设更好
  • 在线视频网站开发方案phpaspnet网站开发实例视频
  • 正常做一个网站多少钱网站开发所遵循
  • 西部数码网站备份领英创建公司主页
  • 中山网站建设文化平台成都电商app开发
  • 无锡网站推广公司排名中国十大网站建设