Linux关于文件IO操作与动静态库

文件相关系统调用接口

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)
int creat(const char *pathname, mode_t mode);

pathname:要打开或创建的目标文件
flags:打开文件时,传入的多个参数选项,可用一下多个常量进行“或”运算构成
flags参数:
O_RDONLY:只读,默认值为此
O_WRONLY :只写
O_RDWR:可读可写
以上三个为必选选项,并且只能选择一个
O_CREAT:若文件不存在,则创建它,此时需要使用mode选项,来指明新文件的访问权限;若文件存在则打开
O_EXCL:一般与O_CREAT一起使用,若文件存在则报错
O_APPEND:写入数据使用追加写方式
O_TRUNC:打开文件时清空原有数据
mode_t mode:不定参
返回值:错误返回-1;成功返回文件描述符,即打开文件的操作句柄。

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

fd:文件描述符,open返回的
buf:指定的缓冲区,数据的放置位置
count:要读取文件的数据长度字节数
返回值:成功时返回读取到的字节数(为0表示读到文件末尾),当返回值小于指定的字节数有可能已经接近文件结尾,或者正在从管道或者终端读取数据,或者read()被信号中断,失败时返回-1。

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

fd:文件描述符,open返回的
buf:指定的缓冲区,要写入数据的缓冲区的首地址
count:要写入文件的数据长度字节数
返回值:成功返回实际写入的字节数,失败时返回-1。

#include <unistd.h>
int close(int fd);

fd:文件标识符
返回值:成功返回0,失败返回-1。

文件描述符fd与FILE结构体对比

文件描述符fd:文件描述符是一个整数,没有负数在open时产生。在Linux系统下,文件描述符主要被用来标识一个文件。打开文件时,操作系统在内存中创建相应的数据结构来描述目标文件。FILE结构体即为这样的数据结构,表示一个已经打开的文件对象。进程执行open系统调用时,需要关联进程和文件,所以每个进程都有一个file指针,指向file_struct文件表,其中包含一个指针数组,每个元素都是一个指向打开文件的指针。本质上,文件描述符就是该数组下标,通过文件描述符,寻找对应的文件。fd起到一个索引的作用,进程通过PCB中的文件描述符表找到该fd所指向的文件指针,内核通过文件对象表来管理系统中各种各样的文件,文件表通过指针指向打开的文件,从而管理整个文件系统。
FILE结构体(文件流指针 FILE *fp):IO相关函数与系统调用接口对应,库函数封装系统调用,访问文件通过fd访问。C标准库当中的FILE结构体内部封装fd。所以FILE比fd更适合跨平台。C中使用文件指针来做为I/O的句柄,文件指针即指向进程的用户空间中的一个FILE结构体,内部有文件描述,有缓冲区。
文件描述符(fd)是唯一的,文件指针(FILE,lib层,即C库)不是唯一的,但指向的对象是唯一的。

shell增加重定向

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <ctype.h>
#include <fcntl.h>
#define N 1024
#define MIX 32

int main()
{
        while (1)
        {
                // 输入提示
                printf("[mini@localhost]# ");
                // 清空缓冲区
                fflush(stdout);
                char buf[N] = {0};
                // 获取输入的字符串,一直接收至遇到换行符
                fgets(buf, N - 1, stdin);
                buf[strlen(buf) - 1] = '\0';
                printf("cmd: [%s]\n", buf);  // 查看数据接收是否正确

                // 解析重定向符号> >>
                int flag = 0;
                char *p = buf, *file = NULL;
                while (*p != '\0')
                {
                        if (*p == '>')
                        {
                                flag = 1;
                                *p = '\0';
                                p++;
                                if (*p == '>')
                                {
                                        flag = 2;
                                        p++;
                                }
                                while (*p == ' ')
                                        p++;
                                file = p;
                                while (!isspace(*p) && *p != '\0')
                                        p++;
                                *p = '\0';
                        }
                        p++;
                }

                // 解析输入字符串,获取需要运行的程序名称及参数
                int argc = 0;
                char *argv[MIX] = {NULL};  // 指针数组
                char *ptr = buf;
                while (*ptr != '\0')
                {
                        if (!isspace(*ptr))
                        {
                                argv[argc] = ptr;
                                argc++;
                                while (!isspace(*ptr) && *ptr != '\0')
                                        ptr++;
                                *ptr = '\0';
                        }
                        ptr++;
                }
                argv[argc] = NULL;
                int i = 0;
                for (i = 0; i < argc; i++)
                        printf("[%s]\n", argv[i]);  // 查看数据解析是否分段正确
                        // 这里输出加\n为了刷新缓冲区内容,如果用空格则会在程序本次循环退出时才输出这段内容

                // 程序替换,调用子进程
                int pid = fork();
                if (pid == 0) // 子进程
                {
                        if (argv[0] == "cd")  // 单独处理cd指令
                                chdir(argv[1]);  // chdir 是C语言中的一个系统调用函数(同cd)
                        // 单独处理重定向符号
                        if (flag == 1)
                        {
                                int fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0664);
                                dup2(fd, 1);  // 重定向一个标准输出到fd中
                        }
                        else if (flag == 2)
                        {
                                int fd = open(file, O_RDWR | O_CREAT | O_APPEND, 0664);
                                dup2(fd, 1);
                        }

                        execvp(argv[0], argv);
                        exit(0);
                }
                waitpid(-1, NULL, 0);  // 父进程等待子进程结束
        }
        return 0;
}
// 经测试运行程序在输入指令的时候,backspace键按下会显示^H,无法删除已输入的字符
// 按下delete键会显示^[[3~,同样无法删除已输入的字符
// 键盘上下左右键按下会显示^[[A^[[B^[[D^[[C
// ls >> test 运行成功将内容写入test文件中,但是输入字符串则失败

静态库与动态库

静态库(lib库名.a):windows下后缀(.lid),程序在编译链接的时候把库的代码链接到可执行文件里,程序运行的时候将不需要静态库。
静态库的生成(gcc、ar):
-c 创建静态库;-r 重新替换改动的.o文件
gcc -c name.c -o name.o
ar -cr libname.a name.o
动态库(lib库名.so):windows下后缀(.dll),程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
动态库的生成(使用gcc):
-fPIC 产生位置无关代码;–share 生成动态/共享库
gcc -fPIC -c name.c -o name.o
gcc --share name.o libname.so
库的使用:
连接的时候使用库:

  1. 将库文件放置到指定的路径下/lib64、/usr/lib64
  2. 设置LIBRARY_PATH环境变量
  3. 通过gcc -L选项设置链接库的默认检索路径,指定库文件所在路径

运行的时候使用库:
只有动态库才会在运行的时候加载库。

  1. 将库文件放置到指定的路径下/lib64、/usr/lib64
  2. 设置LD_LIBRARY_PATH环境变量
动/静态库的练习与使用

add.c

#include <stdio.h>

int add(int a, int b)
{
        return a + b;
}

sub.c

#include <stdio.h>

int sub(int a, int b)
{
        return a - b;
}

mul.c

#include <stdio.h>

int mul(int a, int b)
{
        return a * b;
}

div.c


#include <stdio.h>

int div(int a, int b)
{
        if (b == 0)
                return -1;
        else
                return a / b;
}

main.c


#include <stdio.h>

int main()
{
        int a = 8, b = 2;
        printf("add(a,b) = %d\n", add(a, b));
        printf("sub(a,b) = %d\n", sub(a, b));
        printf("mul(a,b) = %d\n", mul(a, b));
        printf("div(a,b) = %d\n", div(a, b));
        return 0;
}

生成静态库:
在这里插入图片描述
使用静态库:
在这里插入图片描述
删除静态库后已经编译好的程序仍然可以运行:
在这里插入图片描述
生成动态库:
在这里插入图片描述
动态库的使用:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值