打包动静态库以及myshell

本文详细介绍了静态库和动态库的概念及应用场景,包括两者的编译与链接过程,并通过实例演示了如何创建和使用这两种类型的库文件。
静态库
  • 程序编译一般需经预处理、编译、汇编和链接几个步骤
  • 静态库是指在我们的应用中,有一些公共代码是需要反复使用的,就把这些代码编译为“库”文件
  • 在链接步骤中,链接器将从库文件取得所需的代码,复制到生成的可执行文件中的这种库
  • 静态库特点是可执行文件中包含了库代码的一份完整拷贝
  • 缺点就是被多次使用就会有多份冗余拷贝

练习打包静态库

  • 编写简单的 add sub mul div 函数, 编译生成 .o 文件
    这里写图片描述

  • 利用命令生成静态库

ar -rc libmymath.a add.o sub.o mul.o div.o

其中 mymath 是我们的静态库名称

  • 编译, 运行程序
gcc main.c -L . -l mymath
  • -L 选项是指定库的路径
  • -l 选项是指定库名

此时, 即使删掉我们的静态库文件, 程序依然可以运行

这里写图片描述


动态库
  • 动态库又称动态链接库, 英文为DLL,是Dynamic Link Library 的缩写形式
  • DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。
  • 动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。
  • 函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
  • DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL 副本的内容。
  • Windows下动态库为.dll后缀,在linux在为.so后缀。

生成动态库

  • fPIC : 生产与位置无关码
gcc -fPIC -c add.c sub.c chengfa.c div.c

ps:乘法这里我用mul.c会报错, 改成chengfa.c就好了, 还不知道为什么

  • shared : 表示生成共享库格式
gcc -shared -o libmymath.so add.o sub.o chengfa.o div.o
  • 编译运行
gcc main.c -o -L . -l mymath

运行动态库

  • 拷贝 .so 文件到系统共享库目录下, 一般为 /usr/lib
  • 更改 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=.
gcc main.c -l mymath
ifconfig

这里写图片描述


myshell
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>


int main()
{
    while(1)
    {
        printf("[myshell]$ ");
        fflush(stdout);
        char buf[1024];
        ssize_t ret = read(0, buf, (sizeof(buf)) - 1);
        if(ret > 0)
        {
            buf[ret - 1] = 0;
        }

        char *_argv[32];
        char *start = buf;
        char *file = NULL;
        int pipe_flag = 0;// 管道标识符
        int  add_redirect_flag = 0; //追加重定向标识符
        int  redirect_flag = 0; //输出重定向标识符
        _argv[0] = buf;
        int i = 1;
        while(*start)
        {
            if(*start == ' ')
            {
                *start = 0;
                start++;

                //管道实现:当检测到有管道符存在时将命令分为两个数组,管道符以前为一个数组,管道符以后为一个数组
                //然后将管道符处赋值为NULL,开辟子进程,让子进程执行前边的命令,将执行结果写入/tmp/myshell文件中
                //然后父进程等待子进程结束,父进程时打开/tmp/myshell文件,将文件符复制为标准输入,然后执行后面命令。
                if(*start == '|')
                {
                    char *pipe_ch = start;
                    start++;
                    pipe_flag = 1;
                    if(*start == ' ')
                    {
                        *start = 0;
                        start++;
                    }

                }
                if(*start == '>')
                {
                    start++;

                    if(*start == ' ')
                    {
                        *start = 0;
                        start++;
                    }

                    if(*start == '>')
                    {
                        add_redirect_flag = 1;//表示有一个追加重定向
                        start++;
                        if(*start == ' ')
                        {
                            *start = 0;
                            start++;
                        }
                    }
                    file = start;
                    redirect_flag = 1; //表示有一个输出重定向
                    break;
                }
                else
                {
                    _argv[i++] = start;
                }
            }
            else
            {
                start++;
            }
        }
        _argv[i] = NULL;
        pid_t id = fork();
        if(id == 0)
        {
            //子进程
            if(redirect_flag)
            {
                //有重定向, 关闭标准输出
                close(1);
                if(add_redirect_flag)// 追加重定向
                {
                    int ret = open(file, O_WRONLY | O_CREAT | O_APPEND, 0644);
                    execvp(_argv[0], _argv);
                    close(ret);
                }
                else
                {
                    //输出重定向
                    int ret = open(file, O_WRONLY | O_CREAT, 0644);
                    ftruncate(ret, 0); //此函数把ret标识的文件大小置为0, 即先清空文件, 再写入
                    execvp(_argv[0], _argv);
                    close(ret);
                }
            }

            else
            {
                execvp(_argv[0], _argv);
            }
        }
        else
        {
            pid_t ret = wait(NULL);
            if(ret < 0)
            {
                perror("wait");
                return -1;
            }

        }
        if(strcmp(buf, "exit") == 0)
        {
            break;
        }
    }
    return 0;
}

这里写图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值