动态库的加载与进程间通信初步认识

动态库的加载

动态库是一种在运行时被加载到进程中的库。与静态库不同,静态库在编译时被链接到应用程序中,而动态库则在运行时被加载。这允许我们在不重新编译整个应用程序的情况下更新库。

在Linux中,动态库通常以.so(共享对象)为扩展名。在Windows中,它们被称为DLL(动态链接库),并以.dll为扩展名。

示例(Linux环境下):

假设我们有一个名为libexample.so的动态库,其中包含一个函数int add(int a, int b);

首先,我们需要编写动态库的源代码。例如,example.c

#include <stdio.h>  
  
int add(int a, int b) {  
    return a + b;  
}

然后,使用gcc编译为动态库:

gcc -shared -o libexample.so example.c

使用动态库:

编译选项 l:链接动态库,只要库名即可(去掉lib以及版本号) L:链接库所在的路径. 示例:

gcc main.o -o main –L. -example

进程之间通信--管道

在操作系统中,进程间通信(IPC, Inter-Process Communication)是一种允许不同进程之间交换信息或数据的机制。管道(Pipe)是IPC机制中的一种,主要用于具有亲缘关系的进程之间(如父子进程)的通信。管道是一种半双工的通信方式,数据只能单向流动,并且只能在具有共同祖先的进程间使用。

管道的概念

管道是一种特殊的文件,它存在于内核中,用于实现进程间的通信。管道有两个端点,一个用于写入数据(写端),另一个用于读取数据(读端)。数据从写端流入,从读端流出。管道对于管道两端的进程而言,就像一个文件,但它不是普通的文件,而是只存在于内存中的临时文件。

管道有以下特点:

  1. 半双工通信:数据只能单向流动,即数据只能从写端流向读端。
  2. 有界性:管道的大小是有限的,当管道写满时,再写入数据会阻塞或失败。
  3. 生命周期:管道的生命周期随进程,当进程结束时,管道也被销毁。
  4. 匿名性:管道没有名字(也称为无名管道),因此它只能用于具有亲缘关系的进程间的通信。
管道的创建与使用

在Unix/Linux系统中,可以使用pipe系统调用来创建管道。pipe函数原型如下:

#include <unistd.h>  
  
int pipe(int fd[2]);

其中fd是一个包含两个文件描述符的数组,fd[0]是读端,fd[1]是写端。如果pipe调用成功,则返回0;否则返回-1并设置errno

管道通信示例

下面是一个简单的示例,演示了如何使用管道在父子进程间进行通信:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
  
int main() {  
    int fd[2];  
    pid_t pid;  
    char buffer[128];  
  
    // 创建管道  
    if (pipe(fd) == -1) {  
        perror("pipe");  
        exit(EXIT_FAILURE);  
    }  
  
    // 创建子进程  
    pid = fork();  
  
    if (pid == -1) {  
        perror("fork");  
        exit(EXIT_FAILURE);  
    }  
  
    if (pid == 0) { // 子进程  
        // 关闭读端  
        close(fd[0]);  
  
        // 向写端写入数据  
        const char *message = "Hello from child!";  
        write(fd[1], message, strlen(message) + 1);  
  
        // 关闭写端  
        close(fd[1]);  
  
        _exit(EXIT_SUCCESS);  
    } else { // 父进程  
        // 关闭写端  
        close(fd[1]);  
  
        // 从读端读取数据  
        ssize_t bytesRead = read(fd[0], buffer, sizeof(buffer) - 1);  
        if (bytesRead > 0) {  
            buffer[bytesRead] = '\0'; // 确保字符串以null结尾  
            printf("Received from child: %s\n", buffer);  
        }  
  
        // 关闭读端  
        close(fd[0]);  
  
        wait(NULL); // 等待子进程结束  
    }  
  
    return 0;  
}

在这个示例中,我们首先使用pipe系统调用创建了一个管道。然后,我们创建了一个子进程。在子进程中,我们关闭了读端(因为我们不需要从管道中读取数据),然后向写端写入了一条消息。在父进程中,我们关闭了写端(因为我们不需要向管道中写入数据),然后从读端读取子进程发送的消息,并打印出来。

注意,在读取和写入完成后,我们都关闭了相应的文件描述符,以释放资源。同时,在父进程中,我们使用了wait系统调用来等待子进程结束,以确保所有资源都被正确清理。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值