当前位置: 首页 > article >正文

进程操作与管理实战指南

在这里插入图片描述

一、进程基础

进程是操作系统中表示正在运行的一个执行程序。它包含程序计数器(指示当前程序指令的位置)、寄存器文件(包含了计算机的状态信息)、状态信息以及计算机的机器状态(CPU寄存器等)。进程有三种基本状态:就绪状态、执行状态和阻塞状态。

二、进程控制

操作系统提供了各种系统调用来创建、终止、等待和管理进程。

  • fork():创建一个新进程,它是当前进程的一个副本。
  • exec():替换当前进程的映像。
  • wait() / waitpid():等待子进程的终止。
  • exit() / _exit():终止当前进程。
三、信号处理

信号是一种异步通知方式,用于告知接收进程某个事件已经发生。

3.1 常见信号
  • SIGINT:通常由键盘中断产生(Ctrl+C)。
  • SIGTERM:请求进程终止。
  • SIGKILL:强制杀死进程。
  • SIGALRM:定时器超时。
  • SIGSEGV:段错误(非法内存访问)。
  • SIGPIPE:写入管道失败(因为没有读取端)。
  • SIGUSR1/SIGUSR2:用户定义信号,通常用于自定义处理。
3.2 信号处理示例
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

void signalHandler(int sig) {
    switch(sig) {
        case SIGINT:
            printf("Caught SIGINT\n");
            break;
        case SIGTERM:
            printf("Caught SIGTERM\n");
            break;
        default:
            printf("Caught signal %d\n", sig);
    }
}

int main() {
    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);
    while (1) {
        // 主循环
    }
    return 0;
}

在这里插入图片描述

四、多进程并发编程

多进程编程是指在程序中创建多个进程,这些进程可以并行执行不同的任务。

4.1 创建子进程

使用 fork() 函数可以创建一个子进程,该子进程几乎完全复制父进程的所有属性。

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

int main() {
    pid_t pid = fork();
    if (pid == 0) {
        // 子进程
        printf("Child PID: %d\n", getpid());
    } else {
        // 父进程
        printf("Parent PID: %d\n", getpid());
    }
    return 0;
}
五、进程间通信(IPC)

进程间通信是不同进程之间交换数据的一种方式。

5.1 消息队列

消息队列允许进程之间传递结构化的信息。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>

struct message {
    long mtype;
    char mtext[100];
};

int main() {
    key_t key = ftok("/tmp", 65);
    int msqid = msgget(key, 0666 | IPC_CREAT);
    struct message msg;
    strcpy(msg.mtext, "Hello Message Queue!");
    msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
    return 0;
}
5.2 共享内存

共享内存提供了一种让多个进程共享同一块内存区域的方式。

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

int main() {
    key_t key = ftok("/tmp", 65);
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
    char *shm = shmat(shmid, NULL, 0);
    strcpy(shm, "Hello Shared Memory!");
    shmdt(shm);
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}
5.3 套接字

套接字可以用于进程间通信,特别是在不同主机上的进程之间。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8080);
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
    bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    listen(sockfd, 5);
    int connfd = accept(sockfd, NULL, NULL);
    char buffer[1024];
    read(connfd, buffer, 1024);
    printf("Received: %s\n", buffer);
    close(connfd);
    close(sockfd);
    return 0;
}

在这里插入图片描述

六、高级进程管理
6.1 进程组与会话

进程组是一组相关进程的集合,可以作为一个整体来控制。

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

int main() {
    pid_t pid = fork();
    if (pid == 0) {
        setpgid(getpid(), getpid()); // 设置进程组ID
    } else {
        // 父进程可以控制整个进程组
    }
    return 0;
}

会话是一组进程组的集合,通常表示一个用户的交互会话。

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

int main() {
    setsid(); // 创建一个新的会话
    return 0;
}
6.2 进程优先级与调度

可以调整进程的优先级来影响其执行顺序。

#include <sched.h>
#include <stdio.h>

int main() {
    struct sched_param param;
    param.sched_priority = 10;
    sched_setscheduler(0, SCHED_FIFO, &param);
    return 0;
}
七、进程安全与资源管理
7.1 安全编程

在编写多进程应用程序时,必须考虑到安全问题,特别是当涉及到敏感数据处理时。

  • 使用正确的权限设置文件和进程。
  • 使用加密算法保护数据。
7.2 资源回收

确保所有打开的文件描述符和系统资源在进程退出时得到适当的回收。

#include <stdlib.h>

void cleanupFunction() {
    // 清理资源
    // 关闭文件、释放内存等
}

int main() {
    atexit(cleanupFunction);
    // 主循环或其他操作
    return 0;
}

在这里插入图片描述

八、实战指南:实现分布式计算

假设我们需要实现一个简单的分布式计算系统,可以利用进程间的通信来完成任务的分配和结果的收集。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

struct message {
    long mtype;
    char mtext[100];
};

void workerFunction() {
    key_t key = ftok("/tmp", 65);
    int msqid = msgget(key, 0666 | IPC_CREAT);
    struct message msg;
    while (1) {
        msgrcv(msqid, &msg, sizeof(msg.mtext), 1, 0);
        // 处理任务...
        strcpy(msg.mtext, "Task completed.");
        msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
    }
}

int main() {
    pid_t workerPid = fork();
    if (workerPid == 0) { // 子进程作为工作者
        workerFunction();
    } else { // 父进程作为协调者
        key_t key = ftok("/tmp", 65);
        int msqid = msgget(key, 0666 | IPC_CREAT);
        struct message msg;
        strcpy(msg.mtext, "Compute square root of 100.");
        msgsnd(msqid, &msg, sizeof(msg.mtext), 1);
        msgrcv(msqid, &msg, sizeof(msg.mtext), 2, 0);
        printf("%s\n", msg.mtext);
        // 收集其他结果...
    }
    return 0;
}
九、高级应用:实现进程间同步

在多进程环境中,进程间同步是非常重要的,以防止数据竞争和死锁等问题。

9.1 互斥锁(Mutex)

互斥锁可以用来保护共享资源,确保同一时刻只有一个进程可以访问。

#include <pthread.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void lock() {
    pthread_mutex_lock(&mutex);
}

void unlock() {
    pthread_mutex_unlock(&mutex);
}
9.2 信号量(Semaphore)

信号量用于控制多个进程对有限资源的访问。

#include <semaphore.h>

sem_t sem;

void initSemaphore() {
    sem_init(&sem, 0, 1);
}

void acquireSemaphore() {
    sem_wait(&sem);
}

void releaseSemaphore() {
    sem_post(&sem);
}

在这里插入图片描述

十、高级应用:实现多进程之间的资源共享

在多进程环境中,资源共享是一个复杂的问题。可以使用共享内存来实现高效的资源共享。

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

int main() {
    key_t key = ftok("/tmp", 65);
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
    char *shared_memory = shmat(shmid, (void*)0, 0);
    // 使用共享内存
    strcpy(shared_memory, "Hello from shared memory");
    shmdt(shared_memory);
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}
十一、高级应用:实现进程间的可靠通信

在实现进程间通信时,可靠性是一个重要的考虑因素。可以使用多种方法来提高通信的可靠性,比如确认机制、重传机制等。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define PORT 8888

void reliableSend(int sockfd, const char *message) {
    int bytesSent = send(sockfd, message, strlen(message), 0);
    if (bytesSent == -1) {
        perror("Failed to send message");
        exit(EXIT_FAILURE);
    }
    // 等待确认
    char ack[10];
    int bytesReceived = recv(sockfd, ack, 10, 0);
    if (bytesReceived == -1) {
        perror("Failed to receive ACK");
        exit(EXIT_FAILURE);
    }
    if (strncmp(ack, "ACK", 3) != 0) {
        printf("Invalid ACK received: %s\n", ack);
        reliableSend(sockfd, message); // 重发
    }
}

int main() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }
    
    struct sockaddr_in serveraddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &serveraddr.sin_addr);
    
    connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
    
    char buffer[1024];
    while (1) {
        fgets(buffer, 1024, stdin);
        reliableSend(sockfd, buffer);
    }
    
    close(sockfd);
    return 0;
}
十二、高级应用:实现分布式任务队列

假设我们需要实现一个基于消息队列的分布式任务队列系统,可以利用消息队列来完成任务的分配和结果的收集。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define MSGKEY 1234

struct task {
    long mtype;
    char mtext[100];
};

void taskWorker() {
    key_t key = MSGKEY;
    int msqid = msgget(key, 0666 | IPC_CREAT);
    struct task task;
    while (1) {
        msgrcv(msqid, &task, sizeof(task.mtext), 1, 0);
        // 处理任务...
        printf("Worker received task: %s\n", task.mtext);
        strcpy(task.mtext, "Task completed.");
        msgsnd(msqid, &task, sizeof(task.mtext), 2);
    }
}

int main() {
    pid_t workerPid = fork();
    if (workerPid == 0) { // 子进程作为工作者
        taskWorker();
    } else { // 父进程作为协调者
        key_t key = MSGKEY;
        int msqid = msgget(key, 0666 | IPC_CREAT);
        struct task task;
        strcpy(task.mtext, "Compute square root of 100.");
        msgsnd(msqid, &task, sizeof(task.mtext), 1);
        msgrcv(msqid, &task, sizeof(task.mtext), 2, 0);
        printf("%s\n", task.mtext);
        // 发送更多任务...
    }
    return 0;
}

在这里插入图片描述

十三、高级应用:实现分布式日志记录系统

假设我们需要实现一个分布式日志记录系统,可以利用多进程和共享内存来记录和显示日志信息。

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

#define SHMKEY 1234
#define SHMSIZE 1024

struct log_entry {
    char log[SHMSIZE];
};

void loggerFunction() {
    key_t key = SHMKEY;
    int shmid = shmget(key, SHMSIZE, 0666 | IPC_CREAT);
    struct log_entry *log = shmat(shmid, (void*)0, 0);
    while (1) {
        // 读取日志条目
        printf("%s\n", log->log);
        // 清空日志条目
        memset(log->log, 0, SHMSIZE);
    }
}

int main() {
    pid_t loggerPid = fork();
    if (loggerPid == 0) { // 子进程作为日志记录器
        loggerFunction();
    } else { // 父进程作为生产者
        key_t key = SHMKEY;
        int shmid = shmget(key, SHMSIZE, 0666 | IPC_CREAT);
        struct log_entry *log = shmat(shmid, (void*)0, 0);
        strcpy(log->log, "Log entry 1");
        sleep(1);
        strcpy(log->log, "Log entry 2");
        // 记录更多日志条目...
    }
    return 0;
}
十四、高级应用:实现分布式监控系统

假设我们需要实现一个分布式监控系统,可以利用多进程和套接字通信来实时监控各个节点的状态。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define PORT 8888

void monitorFunction() {
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }
    struct sockaddr_in serveraddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &serveraddr.sin_addr);
    char buffer[1024];
    while (1) {
        // 发送监控数据
        sendto(sockfd, "Monitoring data", 16, 0, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
        sleep(1);
    }
    close(sockfd);
}

int main() {
    pid_t monitorPid = fork();
    if (monitorPid == 0) { // 子进程作为监控客户端
        monitorFunction();
    } else { // 父进程作为监控服务端
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd == -1) {
            perror("Socket creation failed");
            exit(EXIT_FAILURE);
        }
        struct sockaddr_in serveraddr;
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_port = htons(PORT);
        inet_pton(AF_INET, "127.0.0.1", &serveraddr.sin_addr);
        bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
        char buffer[1024];
        while (1) {
            // 接收监控数据
            int len = sizeof(serveraddr);
            int bytesReceived = recvfrom(sockfd, buffer, 1024, 0, (struct sockaddr*)&serveraddr, &len);
            buffer[bytesReceived] = '\0';
            printf("%s\n", buffer);
        }
        close(sockfd);
    }
    return 0;
}
十五、高级应用:实现分布式任务调度系统

假设我们需要实现一个分布式任务调度系统,可以利用多进程和消息队列来实现任务的分配和调度。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define MSGKEY 1234

struct task {
    long mtype;
    char mtext[100];
};

void schedulerFunction() {
    key_t key = MSGKEY;
    int msqid = msgget(key, 0666 | IPC_CREAT);
    struct task task;
    while (1) {
        // 分配任务
        strcpy(task.mtext, "Compute square root of 100.");
        msgsnd(msqid, &task, sizeof(task.mtext), 1);
        // 收集结果
        msgrcv(msqid, &task, sizeof(task.mtext), 2, 0);
        printf("%s\n", task.mtext);
        sleep(1);
    }
}

int main() {
    pid_t schedulerPid = fork();
    if (schedulerPid == 0) { // 子进程作为任务调度器
        schedulerFunction();
    } else { // 父进程作为任务执行者
        key_t key = MSGKEY;
        int msqid = msgget(key, 0666 | IPC_CREAT);
        struct task task;
        // 接收任务
        msgrcv(msqid, &task, sizeof(task.mtext), 1, 0);
        // 处理任务...
        printf("Worker received task: %s\n", task.mtext);
        strcpy(task.mtext, "Task completed.");
        // 发送结果
        msgsnd(msqid, &task, sizeof(task.mtext), 2);
        // 执行更多任务...
    }
    return 0;
}
十六、高级应用:实现分布式文件系统

假设我们需要实现一个分布式文件系统,可以利用多进程和套接字通信来实现文件的共享和同步。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define PORT 8888

void serverFunction() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }
    struct sockaddr_in serveraddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &serveraddr.sin_addr);
    bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
    listen(sockfd, 5);
    int clientfd = accept(sockfd, NULL, NULL);
    if (clientfd == -1) {
        perror("Accept failed");
        exit(EXIT_FAILURE);
    }
    char buffer[1024];
    while (1) {
        int bytesReceived = read(clientfd, buffer, 1024);
        buffer[bytesReceived] = '\0';
        printf("%s\n", buffer);
        write(clientfd, "File received", 15);
    }
    close(clientfd);
    close(sockfd);
}

int main() {
    pid_t serverPid = fork();
    if (serverPid == 0) { // 子进程作为服务器
        serverFunction();
    } else { // 父进程作为客户端
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd == -1) {
            perror("Socket creation failed");
            exit(EXIT_FAILURE);
        }
        struct sockaddr_in serveraddr;
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_port = htons(PORT);
        inet_pton(AF_INET, "127.0.0.1", &serveraddr.sin_addr);
        connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
        char buffer[1024];
        while (1) {
            fgets(buffer, 1024, stdin);
            write(sockfd, buffer, strlen(buffer));
        }
        close(sockfd);
    }
    return 0;
}
十七、高级应用:实现分布式数据库复制

假设我们需要实现一个分布式数据库复制系统,可以利用多进程和套接字通信来实现数据的同步。

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define PORT 8888

void replicaFunction() {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }
    struct sockaddr_in serveraddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &serveraddr.sin_addr);
    connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
    char buffer[1024];
    while (1) {
        fgets(buffer, 1024, stdin);
        write(sockfd, buffer, strlen(buffer));
    }
    close(sockfd);
}

int main() {
    pid_t replicaPid = fork();
    if (replicaPid == 0) { // 子进程作为副本
        replicaFunction();
    } else { // 父进程作为主服务器
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd == -1) {
            perror("Socket creation failed");
            exit(EXIT_FAILURE);
        }
        struct sockaddr_in serveraddr;
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_port = htons(PORT);
        inet_pton(AF_INET, "127.0.0.1", &serveraddr.sin_addr);
        bind(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
        listen(sockfd, 5);
        int clientfd = accept(sockfd, NULL, NULL);
        if (clientfd == -1) {
            perror("Accept failed");
            exit(EXIT_FAILURE);
        }
        char buffer[1024];
        while (1) {
            int bytesReceived = read(clientfd, buffer, 1024);
            buffer[bytesReceived] = '\0';
            printf("%s\n", buffer);
            write(clientfd, "Data received", 15);
        }
        close(clientfd);
        close(sockfd);
    }
    return 0;
}
十八、总结

本文进一步详细介绍了C语言中的进程操作技术,包括信号处理、并发编程模型、进程间同步、资源共享、可靠通信等多个方面,并提供了丰富的实战示例代码。通过学习这些知识,你将能够在实际项目中更有效地管理和利用多进程架构。


http://www.kler.cn/a/461057.html

相关文章:

  • 【华为OD-E卷 - 最优资源分配 100分(python、java、c++、js、c)】
  • enzymejest TDD与BDD开发实战
  • OpenHarmony通过挂载镜像来修改镜像内容,RK3566鸿蒙开发板演示
  • flutter 专题二十四 Flutter 响应式状态管理框架GetX
  • 【Rust自学】9.1. 不可恢复的错误以及panic!
  • 前端编码技巧与规范
  • 图论求解平面TSP问题算法复现
  • 《脑网络与智力:基于图神经网络的静息态fMRI数据研究》|文献速递-视觉大模型医疗图像应用
  • 数据结构(链式队列)
  • 开源模型应用落地-FastAPI-助力模型交互-进阶篇-中间件(四)
  • 知识库搭建实战一、(基于 Qianwen 大模型的知识库搭建)
  • [Linux] 服务器CPU信息
  • 2024-12-31-devkit-pipeline
  • 12.31shell脚本
  • FLUX.1-Turbo inpaint
  • Mac 安装 Flutter 提示 A network error occurred while checking
  • “进制转换”公式大集合
  • 软考高项(二十)高级项目管理 ★重点集萃★
  • 宽带、光猫、路由器、WiFi、光纤之间的关系
  • IDEA工程maven reimport无效
  • 海外盲盒系统开发,助力企业全球化发展
  • 进程处理题目
  • C#运动控制系统:雷赛控制卡实用完整例子 C#雷赛开发快速入门 C#雷赛运动控制系统实战例子 C#快速开发雷赛控制卡
  • 汇编基础DOSBox的使用
  • MATLAB关于集合的运算(部分)
  • MyBatisPlus完整技术汇总一