文件操作
包含头文件 fcntl.h
打开文件
int open(const char *pathname, int flags);
flag:(O_RDONLY,O_WRONLY ,O_RDWR )| ( O_APPEND, O_CREAT )
前面三选一,后面可选。如果是CREAT,需要有第三个参数mode,是创建的文件权限。后跟O_EXCL如果文件已经存在,不能创建。
如果使用O_WRONLY,往已存在的文件里写,不会清空原数据,要加O_TRUNC。
函数调用成功返回文件描述符,失败-1.
关闭文件
int close(const char *pathname);
读文件
ssize_t read(int fd, void *buf, size_t count);
参数:文件描述符,存放读的数据, 最大读取字节数。
调用成功返回实际读到的字节,失败返回-1.
写文件
ssize_t write(int fd, void *buf, size_t count);
参数:文件描述符,存放写的数据, 最大写入字节数。
文件描述符
/proc/sys/fs/file-max 是系统最大文件描述符个数
系统允许最大文件描述符,由内存大小决定
ulimit -a 查看系统限制的文件描述符个数,可以手动调整
系统默认打开三个文件描述符作为标准输入输出错误。
ctr + D 相当于从键盘输入文件结束标记EOF
进程与文件描述符
每个进程的PCB里存放文件描述符信息。
新创建的文件描述符一般从3开始增大。
每个文件描述符后有一个指针,指向文件表结构体。
一个进程两次打开同一个文件,创建新文件表,不创建v结点表。
子进程继承父进程文件描述符,文件表引用计数+1.
目录操作
头文件:dirent.h
- 打开目录
DIR *opendir(const char *dirname);
- 读取目录内容
struct dirent *readdir(DIR *pdir);
结构体里包括inode节点数,目录名称
生成静态库
之所以叫做静态,是因为静态库在编译的时候会被直接拷贝一份,复制到目标程序里,这段代码在目标程序里就不会再改变了。
静态库将多个目标文件捆绑,形成一个库文件,对调用者提供服务。
ar -cr libxx.a xx是静态库名
nm xx 查看静态库
- 使用静态库
gcc -L 库文件路径 -l库名
objdump -dS 查看可执行文件的汇编形式
生成动态库
与静态库相反,动态库在编译时并不会被拷贝到目标程序中,目标程序中只会存储指向动态库的引用。等到程序运行时,动态库才会被真正加载进来
gcc -fPIC -shared -o libxx.so
- 链接动态库
首先将库文件放在/usr/lib 目录下
gcc -L 库文件路径 -l库名
方案2:库文件放在指定目录
增加一个配置文件在 /etc/ld.so.conf.d/ 下,配置文件中写入库路径
ldconfig 刷新配置文件
ldd 可执行文件 #命令查看动态库链接错误
动态库运行时加载探究
运行时加载随时更新的库文件,实现软件平滑更新。
编译语句:gcc -ldl
头文件 dlfcn.h
- 打开动态库
void *dlopen(const char *filename, int flag);
flag: RTLD_LAZY 使用时加载库
返回刚打开的动态库句柄
- 找到需要的函数的地址
void *dlsym(int *handle, char *symbol);
返回值用函数指针接收。