可信网站 如何验证,小程序店铺,聊城开发区网络公司排名,seo怎么收费seoLinux 中一切皆文件#xff0c;那么 Linux 文件是什么#xff1f;
在 Linux 中的文件
可以是#xff1a;传统意义上的有序数据集合#xff0c;即#xff1a;文件系统中的物理文件
也可以是#xff1a;设备#xff0c;管道#xff0c;内存。。。(Linux 管理的一切对象…Linux 中一切皆文件那么 Linux 文件是什么
在 Linux 中的文件
可以是传统意义上的有序数据集合即文件系统中的物理文件
也可以是设备管道内存。。。(Linux 管理的一切对象) Linux 中的文件描述符
文件描述符是一个整数值他在内核中被用于标识打开的文件或其它 I/O 资源
当打开一个文件时系统会分配一个文件描述符来唯一标识该文件
文件描述符的范围通常是 0 到 1023
0、1、2 被系统占用分别代表标准输入、标准输出和标准错误进程中可用的文件描述符范围是 3 到 1023 Linux 原生文件编程接口 示例 -- 文件复制 文件复制实现
test1.c
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64#include stdio.h
#include stdlib.h
#include unistd.h
#include memory.h
#include sys/types.h
#include sys/stat.h
#include fcntl.hstatic int copy(int src, int des)
{int ret 0;char buf[256] {0};do{ret read(src, buf, sizeof(buf));ret (ret 0) ? write(des, buf, ret) : ret;} while( ret sizeof(buf) );return (ret 0);
}int main(int argc, char* argv[])
{int src 0;int des 0;if( argc 3 ){if( (src open(argv[1], O_RDONLY)) -1 ){printf(source: open error...\n);exit(-1);}if( (des open(argv[2], O_CREAT | O_WRONLY, 0777)) -1 ){printf(dest: open error...\n);exit(-1);}if( copy(src, des) ){printf(succeed: %s %s\n, argv[1], argv[2]);}else{printf(failed...\n);}close(src);close(des);}else{printf(invalid parameters...\n);}return 0;
}
第 1 - 3 行的宏定义是为了可以拷贝更大的文件
第 19 - 22 行一直不断的从源文件读取 256 字节写入到目的文件直到最后写入的字节不足256字节就认为是拷贝结束了
程序运行结果如下图所示 示例 -- 外存数组
需求
创建一个可以存储 无限 个元素的数组数组大小可动态扩大即动态向数组中追加元素提供统一访问数据元素的方式即以 0 下标作为起始位置 解决方案 时间换空间
C 语言中的数组将数据存储于内存中使用数组前必须定义大小
优点访问速度快 缺点大小必须固定
若要实现可 无限追加 的数组则需要将数据存储于外存中
将数组元素存储于文件中 (不必预先定义大小可实时拓展)根据数组元素大小实时定位文件读写位置并读写固定大小的数据优点数组大小不受限制 缺点访问速度较慢 外存数组接口设计 关键代码设计 外存数组应用示例 外存数组实现
ext_array.h
#ifndef _EXT_ARRAY_H_
#define _EXT_ARRAY_H_typedef void EArray;#define EArray_Init(n, type) EArray_Init_(n, sizeof(type)) #define EArray_Get(type, arr, index) ({ \type ret {0}; \EArray_Get_(arr, index, ret); \ret; \
})#define EArray_Set(type, arr, index, v) ({ \type val v; \EArray_Set_(arr, index, val); \
})#define EArray_Append(type, arr, v) ({ \type val v; \EArray_Append_(arr, val); \
})EArray* EArray_Init_(unsigned int n, unsigned int esize);int EArray_Get_(EArray* arr, unsigned int index, void* e);
int EArray_Set_(EArray* arr, unsigned int index, const void* e);int EArray_Append_(EArray* arr, const void* e);unsigned int EArray_Length(EArray* arr);void EArray_Release(EArray* arr);#endifext_array.c
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64#include time.h
#include stdio.h
#include stdlib.h
#include unistd.h
#include fcntl.h
#include ext_array.htypedef struct _ext_array_
{int fd;char name[128];unsigned int esize;unsigned int length;
}ExtArray;EArray* EArray_Init_(unsigned int n, unsigned int esize)
{ExtArray* ret malloc(sizeof(ExtArray));if( ret ){time_t t {0};time(t);sprintf(ret-name, ./%ld, t);if( (ret-fd open(ret-name, O_CREAT | O_RDWR, 0777)) ! -1 ){int i 0;for(i0; in*esize; i){char c 0;write(ret-fd, c, 1);}ret-esize esize;ret-length n;}else{free(ret);ret NULL;}}return ret;
}int EArray_Get_(EArray* arr, unsigned int index, void* e)
{int ret -1;ExtArray* ea arr;if( ea e (index ea-length) ){lseek(ea-fd, index * ea-esize, SEEK_SET);ret read(ea-fd, e, ea-esize);}return ret;
}int EArray_Set_(EArray* arr, unsigned int index, const void* e)
{int ret -1;ExtArray* ea arr;if( ea e (index ea-length) ){lseek(ea-fd, index * ea-esize, SEEK_SET);ret write(ea-fd, e, ea-esize);}return ret;
}int EArray_Append_(EArray* arr, const void* e)
{int ret -1;ExtArray* ea arr;if( ea e ){lseek(ea-fd, 0, SEEK_END);ret write(ea-fd, e, ea-esize);if( ret ! -1 ){ea-length 1;}}return ret;
}unsigned int EArray_Length(EArray* arr)
{int ret -1;ExtArray* ea arr;if( ea ){ret ea-length;}return ret;
}void EArray_Release(EArray* arr)
{ExtArray* ea arr;if( ea ){close(ea-fd);unlink(ea-name);free(ea);}
}test2.c #include stdio.h
#include stdlib.h
#include unistd.h
#include memory.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h#include ext_array.hint main(int argc, char* argv[])
{EArray* arr EArray_Init(5, int);int i 0;printf(length %d\n, EArray_Length(arr));for(i0; iEArray_Length(arr); i){EArray_Set(int, arr, i, i 1);}EArray_Append(int, arr, 1000);printf(length %d\n, EArray_Length(arr));for(i0; iEArray_Length(arr); i){int val EArray_Get(int, arr, i);printf(val %d\n, val);}EArray_Release(arr);return 0;
}
EArray_Init_(...) 函数用于创建一个随机文件名的文件用于存储数组的内容将这片预定义的空间先写为0
EArray_Get_(...) 和 EArray_Set_(...) 函数通过 lseek(...) 定位到要读写元素的位置然后进行读写
EArray_Append_(...) 函数通过 lseek(...) 定位到文件的末尾然后再进行写入操作
我们定义 EArray_Get、EArray_Set 和 EArray_Append 这三个宏是因为这三个函数末尾带下划线的版本需要传入元素的地址而不是数据而传入地址我们每次调用的时候都必须先定义出一个变量出来再传入这个变量的地址这样使用很不方便所以才定义这三个宏可以直接传入数据 Linux 一切皆文件
ASCII C 文件操作
stdin 标准输入流stdout 标准输出流stderr 标准错误输出
Linux 原生文件操作
1 显示设备0 输入设备2 错误设备 以文件的方式操作设备 通过 ASCII C 文件操作 输入 / 输出 通过 Linux 文件操作 输入 / 输出 设备文件操作
test3.c #include stdio.h
#include stdlib.h
#include unistd.h
#include memory.h
#include sys/types.h
#include sys/stat.h
#include fcntl.hstatic void ascii_file_io()
{char buf[16] {0};int i 0;char c 0;do{fread(c, sizeof(c), 1, stdin);if( c \n )break;elsebuf[i] c;} while( i 16);fwrite(output: , 1, 8, stdout);fwrite(buf, 1, i, stdout);fwrite(\n, 1, 1, stdout);
}static void linux_file_io()
{char buf[16] {0};int i 0;/*do{char c 0;read(0, c, 1);if( c \n )break;elsebuf[i] c;} while( i 16);*/i read(0, buf, sizeof(buf));write(1, output: , 8);write(1, buf, i);write(1, \n, 1);
}
int main(int argc, char* argv[])
{// ascii_file_io();linux_file_io();return 0;
}
第 50 行我们读取文件描述符 0(标准输入)标准输入默认为行缓冲所以我们在键盘上输入换行符read 才会返回
程序运行结果如下图所示