ubuntu

ubuntu进程间通信怎么做

小樊
46
2025-04-11 06:54:32
栏目: 智能运维

在Ubuntu系统中,进程间通信(IPC)可以通过多种方式实现,以下是一些常见的IPC方法:

  1. 管道(Pipes):

    • 匿名管道:通常用于父子进程之间的通信。
    • 命名管道(FIFO):允许无亲缘关系的进程之间进行通信。
  2. 消息队列(Message Queues):

    • System V消息队列
    • POSIX消息队列
  3. 共享内存(Shared Memory):

    • System V共享内存
    • POSIX共享内存
  4. 信号(Signals):

    • 用于进程间简单事件的通知。
  5. 信号量(Semaphores):

    • 用于进程同步,控制多个进程对共享资源的访问。
  6. 套接字(Sockets):

    • 支持本地进程间通信(如Unix Domain Sockets)和跨网络通信。
  7. 内存映射文件(Memory-mapped Files):

    • 允许将文件或其他对象映射到进程的地址空间,从而实现数据共享。

下面是一些简单的示例,展示如何在Ubuntu中使用这些IPC机制:

匿名管道示例

#include <stdio.h>
#include <unistd.h>

int main() {
    int pipefd[2];
    char buffer[10];

    // 创建匿名管道
    if (pipe(pipefd) == -1) {
        perror("pipe");
        return 1;
    }

    // 创建子进程
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
        return 1;
    }

    if (pid == 0) { // 子进程
        close(pipefd[1]); // 关闭写端
        read(pipefd[0], buffer, sizeof(buffer)); // 读取消息
        printf("Child received: %s\n", buffer);
        close(pipefd[0]);
    } else { // 父进程
        close(pipefd[0]); // 关闭读端
        write(pipefd[1], "Hello from parent!", 20); // 发送消息
        close(pipefd[1]);
        wait(NULL); // 等待子进程结束
    }

    return 0;
}

命名管道(FIFO)示例

# 创建命名管道
mkfifo myfifo

# 写入数据到命名管道
echo "Hello FIFO" > myfifo &

# 从命名管道读取数据
cat myfifo

共享内存示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

int main() {
    key_t key = ftok("shmfile", 65);
    int shmid = shmget(key, 1024, 0666|IPC_CREAT);
    char *str = (char*) shmat(shmid, (void*)0, 0);

    strcpy(str, "Hello shared memory");
    printf("Shared memory: %s\n", str);

    shmdt(str);
    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

信号量示例

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

int main() {
    key_t key = ftok("semfile", 65);
    int semid = semget(key, 1, 0666|IPC_CREAT);

    union semun arg;
    arg.val = 1; // 初始化信号量为1
    semctl(semid, 0, SETVAL, arg);

    // 使用semop进行P操作(等待信号量)
    struct sembuf sb = {0, -1, SEM_UNDO};
    semop(semid, &sb, 1);

    printf("Semaphore value: %d\n", semctl(semid, 0, GETVAL, arg));

    // 使用semop进行V操作(释放信号量)
    sb.sem_op = 1;
    semop(semid, &sb, 1);

    semctl(semid, 0, IPC_RMID, arg);

    return 0;
}

套接字示例

// Unix Domain Sockets 示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

int main() {
    int sockfd;
    struct sockaddr_un addr;
    char buffer[1024];

    // 创建套接字
    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        return 1;
    }

    // 设置地址结构
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, "/tmp/uds.sock", sizeof(addr.sun_path)-1);

    // 绑定套接字
    if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        perror("bind");
        return 1;
    }

    // 监听连接
    listen(sockfd, 5);

    // 接受连接
    int clientfd = accept(sockfd, NULL, NULL);
    if (clientfd == -1) {
        perror("accept");
        return 1;
    }

    // 读取数据
    read(clientfd, buffer, sizeof(buffer));
    printf("Received: %s\n", buffer);

    // 发送数据
    write(clientfd, "Hello from server!", 20);

    // 关闭套接字
    close(clientfd);
    close(sockfd);

    return 0;
}

这些示例展示了如何在Ubuntu中使用不同的IPC机制。在实际应用中,你需要根据具体需求选择合适的IPC方法,并编写相应的代码。记得在编译C程序时链接必要的库,例如-lrt用于实时库,-lpthread用于线程支持等。

0
看了该问题的人还看了