C语言 多进程编程(七)信号量

简介: 本文档详细介绍了进程间通信中的信号量机制。首先解释了资源竞争、临界资源和临界区的概念,并重点阐述了信号量如何解决这些问题。信号量作为一种协调共享资源访问的机制,包括互斥和同步两方面。文档还详细描述了无名信号量的初始化、等待、释放及销毁等操作,并提供了相应的 C 语言示例代码。此外,还介绍了如何创建信号量集合、初始化信号量以及信号量的操作方法。最后,通过实际示例展示了信号量在进程互斥和同步中的应用,包括如何使用信号量避免资源竞争,并实现了父子进程间的同步输出。附带的 `sem.h` 和 `sem.c` 文件提供了信号量操作的具体实现。

进程间通信之信号量

资源竞争

多个进程竞争同一资源时,会发生资源竞争。
资源竞争会导致进程的执行出现不可预测的结果。

临界资源

不允许同时有多个进程访问的资源, 包括硬件资源 (CPU、内存、存储器以及其他外
围设备) 与软件资源(共享代码段、共享数据结构)

临界区

多个进程共享的资源被称为临界资源,
这些资源被保护在一个临界区中,
只有进入临界区的进程才能访问临界资源。

信号量

信号量是一种进程间通信机制,用于协调对共享资源的访问。

多进程对stdout资源的竞争


//多进程对stdout资源的竞争

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int main(){
   
   

    pid_t cpid;
    cpid = fork();//创建子进程
    if(cpid < 0){
   
   
        printf("fork error\n");//fork失败
        exit(EXIT_FAILURE);//EXIT_FAILURE表示程序运行失败
    } else if(cpid == 0){
   
   //子进程
        while(1){
   
   
            printf("------------------------\n");
            printf("C Start.\n");
            sleep(1);
            printf("C End.\n");
            printf("------------------------\n");
        }
    } else{
   
   //父进程
        while(1){
   
   
            printf("------------------------\n");
            printf("P Start.\n");
            sleep(1);
            printf("P End.\n");
            printf("------------------------\n");
        }

         wait(NULL); //等待子进程结束
    }



    return 0;
}

代码的输出混乱:

------------------------
P Start.
------------------------
C Start.
P End.
------------------------
C End.
------------------------
------------------------
P Start.
------------------------
C Start.
P End.
C End.
------------------------
------------------------

同步和互斥

互斥

互斥是指进程独占资源,使得其他进程无法访问该资源。

同步

同步是指进程间通信,用于协调进程的执行。
同步在互斥的基础上增加了进程对临界资源的访问顺序
进程主要的同步与互斥手段是信号量

信号量

信号量,由内核维护的整数,其值被限制为大于或等于0;
信号可以执行一下操作:

  • 将信号量设置成一个具体的值;
  • 在信号量当前的基础上加上一个数值;
  • 在信号量当前值的基础上减上一个数值;
  • 等待信号量的值为0;

    一般信号量分为

    • 二值信号量:一般指的是信号量值为1,可以理解为只对应一个资源
    • 计数信号量:一般指的是值大于等于2,可以理解为对应多个资源

在linux系统中使用ipcs -s 查询系统中信号量

无名信号量

sem_init()初始化无名信号量

函数头文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>   
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);

函数功能:初始化一个无名信号量;

函数参数:
- sem: 指向信号量的指针;
- pshared: 共享标志位, 
      - 0表示不共享, 两个线程间同步
      - 非0表示共享,两个进程间同步;

- value: 信号量的初始值;
       -  如果是1表示可以获取信号量
       - 如果是0表示不可以获取信号量

函数返回值:
- 成功: 返回0;
- 失败: 返回-1, 并设置errno;



### sem_wait()等待信号量

函数头文件:

```c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>   
#include <semaphore.h>
int sem_wait(sem_t *sem);

函数功能:等待信号量;

函数参数:

  • sem: 指向信号量的指针;(将信号量的值-1)
  • 如果信号量的值已经是0了,则sem_wait会阻塞,等到能执行减1操作为止

函数返回值:

  • 成功: 返回0;
  • 失败: 返回-1, 并设置errno;

sem_post()释放信号量

函数头文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>   
#include <semaphore.h>
int sem_post(sem_t *sem);

函数功能:

释放信号量;(将信号量的值+1)

函数参数:

  • sem: 指向信号量的指针;

函数返回值:

  • 成功: 返回0;
  • 失败: 返回-1, 并设置errno;

sem_destroy()销毁信号量

函数头文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>   
#include <semaphore.h>  
int sem_destroy(sem_t *sem);

函数功能:销毁信号量;

函数参数:

  • sem: 指向信号量的指针;

函数返回值:

  • 成功: 返回0;
  • 失败: 返回-1, 并设置errno;
  • 如果信号量已经被销毁,则再次调用 sem_destroy() 不会有任何作用, 不会报错;

创建信号量集合

调用 semget() 函数

函数头文件:

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


int semget(key_t key, int nsems, int semflg);

函数功能:创建一个信号量集合;

函数参数:

  • key: 信号量集合的键值, 用于标识信号量集合;由ftok()函数生成;
  • nsems: 信号量集合中信号量的个数;
  • semflg: 信号量集合的标志位, 用于设置信号量集合的属性;
    • IPC_CREAT: 如果key对应的信号量集合不存在, 则创建新的信号量集合;
    • IPC_EXCL: 如果key对应的信号量集合已经存在, 则返回-1;
    • 权限标志

函数返回值:

  • 成功: 返回信号量集合的ID;
  • 失败: 返回-1, 并设置errno;
//多进程对stdout资源的竞争

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define MSG_PATH "/home/gopher"
#define MSG_ID 88
int main(){
   
   
    key_t key;
    //通过文件路径和ID生成key,
    key= ftok(MSG_PATH,MSG_ID);
    if(key==-1){
   
   
        printf("ftok()");
        exit(EXIT_FAILURE);
    }

    //创建信号量集合,包含了一个信号量,编号为0
    int semid=semget(key,1,IPC_CREAT|0666);
    if(semid==-1){
   
   
        printf("semget()");
        exit(EXIT_FAILURE);
    }

    return 0;
}

创建出一个信号量集合,包含了一个信号量,编号为0

img_47.png

初始化信号量

调用 semctl() 函数

函数头文件:

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


int semctl(int semid, int semnum, int cmd, ... /* arg */ );

函数功能:对信号量集合中的信号量进行操作;根据cmd 决定当前函数的功能;

函数参数:

  • semid: 信号量集合的ID;
  • semnum: 信号量的编号;编号从0开始;
  • cmd: 信号量操作命令;
    • SETVAL:设置信号量的值。
    • GETPID:返回最后一个执行 semop 操作的进程的PID。
    • GETVAL:返回指定信号量的值。不需要第四个参数
    • GETALL:返回信号量集中所有信号量的值。
    • GETNCNT:返回正在等待信号量增加的进程数。
    • GETZCNT:返回正在等待信号量变为零的进程数。
    • SETALL:设置信号量集中所有信号量的值。
    • IPC_STAT:获取信号量集的状态信息。 第二参数被忽略,第四个参数buf选项
    • IPC_SET:设置信号量集的状态信息。第二参数被忽略,第四个参数buf选项
    • IPC_RMID:删除信号量集。
  • ... :是属于可变参参数列表,根据不同的命令有不同的参数;

函数返回值:

  • 成功: 根据不同的cmd, 返回不同的结果;
  • GETPID:返回等待最后一个 semop 操作的进程的 PID。

    GETVAL:返回指定信号量的值。
    ls
    GETALL:如果成功,返回 0。

    GETNCNT:返回正在等待增加信号量值的进程数量。

    GETZCNT:返回正在等待信号量值为零的进程数量。

    IPC_STAT:如果成功,返回 0。

    IPC_SET:如果成功,返回 0。

    IPC_RMID:如果成功,返回 0。

    SETVAL:如果成功,返回 0。

    SETALL:如果成功,返回 0。

  • 失败: 返回-1, 并设置errno;

//多进程对stdout资源的竞争

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#define MSG_PATH "/home/gopher"
#define MSG_ID 88

union semun{
   
   
    int val;
};
int main(){
   
   
    key_t key;
    //通过文件路径和ID生成key,
    key= ftok(MSG_PATH,MSG_ID);
    if(key==-1){
   
   
        printf("ftok()");
        exit(EXIT_FAILURE);
    }

    //创建信号量集合,包含了一个信号量,编号为0
    int semid=semget(key,1,IPC_CREAT|0666);
    if(semid==-1){
   
   
        printf("semget()");
        exit(EXIT_FAILURE);
    }

      union semun s;//定义一个联合体,用于设置信号量的值
      s.val=1;//设置信号量的值为1
      int ret=semctl(semid,0,SETVAL,s);//设置semid信号集中的第编号为0的信号量的值为1
      if(ret==-1){
   
   
          printf("semctl()");
          exit(EXIT_FAILURE);
      }

    return 0;
}

信号量操作

  • 信号量可以进⾏以下操作:
    • 对信号量的值加 1
    • 对信号量的值减 1
    • 等待信号量的值为 0

调用 semop() 函数

函数头文件:

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


int semop(int semid, struct sembuf *sops, size_t nsops);

函数功能:对信号量集合中的信号量进行操作;

函数参数:

  • semid: 信号量集合的ID;
  • sops: 信号量操作结构体指针
  • nsops: 信号量操作结构体的个数;

函数返回值:

  • 成功: 返回 0;
  • 失败: 返回-1, 并设置errno;

struct sembuf *sops: 信号量操作结构体指针
```c
struct sembuf
{
unsigned short int sem_num;//信号量编号,从0开始
short int sem_op; //信号量操作
//-1:占用资源
// +1:释放资源
// 0:等待资源

short int sem_flg; //信号量操作标志位
//IPC_NOWAIT:非阻塞,在信号量的值为0时,立即返回
// SEM_UNDO:在进程终止时,会自动释放信号量
};


## 信号量集合删除

调用 semctl() 函数 ,设置命令为 IPC_RMID

在使用 semctl() 函数删除信号量集合时,需要注意第三个参数会被忽略

## 信号量互斥应用

> 使用信号量实现进程间互斥,同一时间只有一个进程访问临界资源
> 
> 
1.创建sem.h

```c

#ifndef _mySEM_H_
#define _mySEM_H_
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

//创建信号量集
int sem_create(int names,unsigned short value[]);
//占用信号量
int sem_p(int semid,int semnum);
//释放信号量
int sem_v(int semid,int semnum);
//删除信号量集
int sem_delete(int semid);


#endif /* _SEM_H_ */

2.创建sem.c


#include "sem.h"

union semun {
   
   
               int              val;    val 是一个整数类型,用于 SETVAL 命令,该命令用于设置信号量的值。
               struct semid_ds *buf;    一个指向 struct semid_ds 结构的指针。semid_ds 结构用于存储信号量集合的状态信息。
                                          buf 用于 IPC_STAT 和 IPC_SET 命令,分别用于获取和设置信号量集合的状态信息。
               unsigned short  *array;  一个指向无符号短整数数组的指针。
                                      该数组用于 GETALL 和 SETALL 命令,分别用于获取和设置信号量集合中所有信号量的值
               struct seminfo  *__buf;  一个指向 struct seminfo 结构的指针。seminfo 结构用于存储信号量集合的详细信息。
                                      __buf 用于 IPC_INFO 命令,该命令用于获取信号量集合的详细信息。这个成员是 Linux 特定的。
           };


//创建信号量集
//@param names 信号量集的个数
//@param value 信号量集的初始值
//@return 成功返回信号量集的id,失败返回-1
int sem_create(int names,unsigned short value[]){
   
   
    key_t key;
    //创建key
    key= ftok(".",88);
    if (key == -1){
   
   
        perror("ftok");
        return -1;
    }

    //创建信号量集
    int semid;
    semid = semget(key,names,IPC_CREAT|0666);//参数:key,信号量集的个数,权限
    if (semid == -1)
    {
   
   
        perror("semget");
        return -1;
    }


    union semun s; //定义union semun
    s.array = value;//将value数组赋值给union semun的array成员
    //初始化信号量集
    int ret=semctl(semid,0,SETALL,s);//这个操作将value数组中的值设置到信号量集中
    if (ret == -1){
   
   
        perror("semctl");
        return -1;
    }

    return semid;


}



//占用信号量
//@param semid 信号量集的id
//@param semnum 信号量的编号
int sem_p(int semid,int semnum){
   
   
    struct sembuf sem_b;//定义一个信号量操作结构体
    sem_b.sem_num=semnum;//信号量编号
    sem_b.sem_op= -1;//占用资源
    sem_b.sem_flg=SEM_UNDO;//在进程终止时,会自动释放信号量
    //操作1个信号量,如果操作多个信号量,需要创建sembuf结构体的数组
    int r= semop(semid,&sem_b,1); //失败返回-1,并设置errno   
    return r;
}
//释放信号量
int sem_v(int semid,int semnum){
   
   
 struct sembuf sem_b;//定义一个信号量操作结构体
    sem_b.sem_num=semnum;//信号量编号
    sem_b.sem_op= 1;//释放资源
    sem_b.sem_flg=SEM_UNDO;//在进程终止时,会自动释放信号量,

    int r= semop(semid,&sem_b,1); //操作1个信号量,如果操作多个信号量,需要创建sembuf结构体的数组
    //失败返回-1,并设置errno   
    return r;
}
//删除信号量集
int sem_delete(int semid){
   
   
    int r= semctl(semid,0,IPC_RMID); //删除信号量集
    return r;
}

3.创建main.c


// 多进程对stdout资源的竞争

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include "sem.h"
int main()
{
   
   

    int semid;// 信号量ID
    unsigned short values[] = {
   
   1};// 信号量初始值

    semid = sem_create(1, values);
    if(semid == -1 ){
   
   
        printf("sem_create error\n");
        exit(EXIT_FAILURE);
    }




    pid_t cpid;// 子进程ID

    cpid = fork(); // 创建子进程
    if (cpid < 0)
    {
   
   
        printf("fork error\n"); // fork失败
        exit(EXIT_FAILURE);     // EXIT_FAILURE表示程序运行失败
    }
    else if (cpid == 0)
    {
   
    // 子进程
        while (1)
        {
   
   
            sem_p(semid,0);
            printf("------------------------\n");
            printf("C Start.\n");
            sleep(1);
            printf("C End.\n");
            printf("------------------------\n");
            sem_v(semid,0);

        }
    }
    else
    {
   
    // 父进程
        while (1)
        {
   
   
            sem_p(semid,0);
            printf("------------------------\n");
            printf("P Start.\n");
            sleep(1);
            printf("P End.\n");
            printf("------------------------\n");
            sem_v(semid,0);
        }

        wait(NULL); // 等待子进程结束
    }

    return 0;
}

4.编译运行



------------------------
P Start.
P End.
------------------------
------------------------
C Start.
C End.
------------------------
------------------------
P Start.
P End.
------------------------
------------------------
C Start.
C End.
----------

信号量同步应用

同步在互斥的基础上增加了进程对临界资源的访问顺序
进程主要的同步与互斥手段是信号量

示例:

创建⽗⼦进程,输出 “ABA” 字符串,具体需求如下:
⽗进程 输出 A
⼦进程 输出 B
⽗进程 输出 A ,输出换⾏
能够循环输出 “ABA” 字符

基本思路:

通过创建⼀个信号量集合,包含 2 个信号量,⼀个信号量 编号为 0
(SEM_CONTROL_P)控制⽗进程的运⾏与暂停,⼀个信号量 编号为 1
(SEM_CONTROL_C) 控制⼦进程的运⾏与暂停

// 多进程对stdout资源的竞争

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include "sem.h"

#define SEM_C = 1
#define SEM_P = 0
// todo 创建一个信号量集合,集合中两个信号量,信号量0的值是1,信号量1的值是0;
int main()
{
   
   

    int semid;                         // 信号量ID
    unsigned short values[2] = {
   
   1, 0}; // 信号量初始值
    // todo 创建一个信号量集合,集合中两个信号量,信号量编号0的值是1,信号量编号1的值是0;
    semid = sem_create(2, values);
    if (semid == -1)
    {
   
   
        printf("sem_create error\n");
        exit(EXIT_FAILURE);
    }

    pid_t cpid; // 子进程ID

    cpid = fork(); // 创建子进程
    if (cpid < 0)
    {
   
   
        printf("fork error\n"); // fork失败
        exit(EXIT_FAILURE);     // EXIT_FAILURE表示程序运行失败
    }
    else if (cpid == 0)
    {
   
    // 子进程
        while (1)
        {
   
   
            sem_p(semid, 1); //?占用信号量编号1,信号量编号1的值初始是0 ,在这里阻塞,等待父进程操作
            printf("B");
            fflush(stdout); // 刷新缓冲
            sem_v(semid, 0); //!释放信号量编号0,信号量编号0的值 0=>1,此时父进程不再阻塞,第二次占用0

        }
    }
    else
    {
   
    // 父进程
        while (1)
        {
   
   
            //@param semid 信号量集的id
            //@param semnum 信号量的编号
            sem_p(semid, 0); //?占用信号量编号0,信号量编号0的值 1=>0
            printf("A");
            fflush(stdout);  // 刷新缓冲
            sem_v(semid, 1); //?释放信号量编号1,信号量编号1的值 0=>1,此时子进程不再阻塞
            sem_p(semid, 0); //!第二次占用信号量编号0,信号量编号0的值是0,在这里阻塞,等待子进程的操作
            printf("A\n");
            fflush(stdout);  // 刷新缓冲
            sem_v(semid, 0);
            sleep(1);

        }

        wait(NULL); // 等待子进程结束
    }

    return 0;
}

+

sem.h:

#ifndef __SEM_H__
#define __SEM_H__
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>

#define SHM_PATH "/home/gopher"
#define SHM_ID 1234
//初始化信号量
int sem_init(int num);
//信号量P操作
int sem_p(int semid, int num);
//信号量V操作
int sem_v(int semid, int num);
//销毁信号量
int sem_destroy(int semid);

#endif

sem.c:


#include "sem.h"
//初始化信号量
//@param num 信号量的数量
int sem_init(int num){
   
   
    key_t key;//消息队列的key
    //通过文件路径和ID生成key,
    key= ftok(SHM_PATH,SHM_ID);
    if(key==-1){
   
   
        printf("ftok() error\n");
        exit(EXIT_FAILURE);
    }
    printf("key: %d\n",key);

    //创建共享内存
    //@param key 共享内存的key
    //@param nsems 共享内存的数量
    //@param semflg 共享内存的标志
    int semid = semget(key,2,IPC_CREAT|0666);
    if(semid==-1){
   
   
        if (errno== EEXIST ){
   
   //EEXIST文件存在
                printf("信号量集合已存在\n");//提示已存在
              if(-1==(semid = semget(key,2,IPC_CREAT|0666))){
   
   
                  return semid;
              }
        }
        printf("semget()");
        exit(EXIT_FAILURE);
    }

    //初始化信号量
    for(int i = 0; i < num; i++){
   
   
        //设置信号量的值
        if(-1 == semctl(semid, i, SETVAL, !i)){
   
   
            printf("semctl() error\n");
            exit(EXIT_FAILURE);
        }
    }
    return semid;
}
//信号量P操作
int sem_p(int semid, int num){
   
   
    struct sembuf s={
   
   
            .sem_num=num,//信号量的编号
           .sem_op=-1,//P操作
           .sem_flg=0 //操作标志
    };
    //P操作
    //@param semid 信号量集合ID
    //@param s 信号量操作结构体
    //@param nsops 信号量操作结构体的数量
    semop(semid,&s,1);
    return 0;
}
//信号量V操作
int sem_v(int semid, int num){
   
   
    struct sembuf s={
   
   
            .sem_num=num,//信号量的编号
            .sem_op=1,//V操作
            .sem_flg=0//操作标志
    };
    //V操作
    //@param semid 信号量集合ID
    //@param s 信号量操作结构体
    //@param nsops 信号量操作结构体的数量
    semop(semid,&s,1);
    return 0;
}
//销毁信号量
int sem_destroy(int semid){
   
   
    //销毁信号量集合
    //@param semid 信号量集合ID
    //@param semnum 信号量的数量
    //@param semflg 信号量的操作标志//删除信号灯集 第二参数被忽略,第4个参数不用填写
    semctl(semid,0,IPC_RMID);

    return 0;
}
相关文章
|
2天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
35 13
|
18天前
|
存储 编译器 C语言
【C语言】数据类型全解析:编程效率提升的秘诀
在C语言中,合理选择和使用数据类型是编程的关键。通过深入理解基本数据类型和派生数据类型,掌握类型限定符和扩展技巧,可以编写出高效、稳定、可维护的代码。无论是在普通应用还是嵌入式系统中,数据类型的合理使用都能显著提升程序的性能和可靠性。
40 8
|
18天前
|
消息中间件 Unix Linux
【C语言】进程和线程详解
在现代操作系统中,进程和线程是实现并发执行的两种主要方式。理解它们的区别和各自的应用场景对于编写高效的并发程序至关重要。
46 6
|
21天前
|
C语言
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性。本文探讨了C语言中的错误类型(如语法错误、运行时错误)、基本处理方法(如返回值、全局变量、自定义异常处理)、常见策略(如检查返回值、设置标志位、记录错误信息)及错误处理函数(如perror、strerror)。强调了不忽略错误、保持处理一致性及避免过度处理的重要性,并通过文件操作和网络编程实例展示了错误处理的应用。
55 4
|
2月前
|
NoSQL C语言 索引
十二个C语言新手编程时常犯的错误及解决方式
C语言初学者常遇错误包括语法错误、未初始化变量、数组越界、指针错误、函数声明与定义不匹配、忘记包含头文件、格式化字符串错误、忘记返回值、内存泄漏、逻辑错误、字符串未正确终止及递归无退出条件。解决方法涉及仔细检查代码、初始化变量、确保索引有效、正确使用指针与格式化字符串、包含必要头文件、使用调试工具跟踪逻辑、避免内存泄漏及确保递归有基准情况。利用调试器、编写注释及查阅资料也有助于提高编程效率。避免这些错误可使代码更稳定、高效。
422 12
|
3月前
|
安全 开发者 Python
揭秘Python IPC:进程间的秘密对话,让你的系统编程更上一层楼
【9月更文挑战第8天】在系统编程中,进程间通信(IPC)是实现多进程协作的关键技术。IPC机制如管道、队列、共享内存和套接字,使进程能在独立内存空间中共享信息,提升系统并发性和灵活性。Python提供了丰富的IPC工具,如`multiprocessing.Pipe()`和`multiprocessing.Queue()`,简化了进程间通信的实现。本文将从理论到实践,详细介绍各种IPC机制的特点和应用场景,帮助开发者构建高效、可靠的多进程应用。掌握Python IPC,让系统编程更加得心应手。
38 4
|
3月前
|
网络协议 C语言
C语言 网络编程(十三)并发的TCP服务端-以进程完成功能
这段代码实现了一个基于TCP协议的多进程并发服务端和客户端程序。服务端通过创建子进程来处理多个客户端连接,解决了粘包问题,并支持不定长数据传输。客户端则循环发送数据并接收服务端回传的信息,同样处理了粘包问题。程序通过自定义的数据长度前缀确保了数据的完整性和准确性。
|
3月前
|
C语言
C语言 网络编程(八)并发的UDP服务端 以进程完成功能
这段代码展示了如何使用多进程处理 UDP 客户端和服务端通信。客户端通过发送登录请求与服务端建立连接,并与服务端新建的子进程进行数据交换。服务端则负责接收请求,验证登录信息,并创建子进程处理客户端的具体请求。子进程会创建一个新的套接字与客户端通信,实现数据收发功能。此方案有效利用了多进程的优势,提高了系统的并发处理能力。
|
3月前
|
缓存 Linux C语言
C语言 多进程编程(六)共享内存
本文介绍了Linux系统下的多进程通信机制——共享内存的使用方法。首先详细讲解了如何通过`shmget()`函数创建共享内存,并提供了示例代码。接着介绍了如何利用`shmctl()`函数删除共享内存。随后,文章解释了共享内存映射的概念及其实现方法,包括使用`shmat()`函数进行映射以及使用`shmdt()`函数解除映射,并给出了相应的示例代码。最后,展示了如何在共享内存中读写数据的具体操作流程。
|
5月前
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能

相关实验场景

更多