linux多进程共享内存_python多进程用不了

linux多进程共享内存_python多进程用不了共享进程:shmget(),shmat(),shmdt(),shmctl()_linuxc++shmget

为什么要引入共享进程

共享进程顾名思义,就是允许多个程序共同使用一个进程。共享内存是进程间通信最快的方式,仅在建立共享内存区域时需要系统调用,以后所有共享内存访问都处理为常规内存访问。为此,为了节省系统资源,提高进程间通信速度,我们需要引入共享进程的概念.

共享进程常用的函数共有四个:shmget(),shmat(),shmdt(),shmctl().我将依次介绍.

1.shmget()

shmget()函数是用于获取共享内存段的标识符的系统调用 ,其定义如下:

#include <sys/shm.h>    
int shmget(key_t key, size_t size, int shmflg);

其中key代表共享内存的键值,通常由ftok()函数生成;size为共享内存的大小(以字节为单位;shmflg为共享内存的权限标志,常用的权限标志有IPC_CREATIPC_EXCL0666等。

若执行成功,shmget()函数返回共享内存的标识符(一个非负整数)。如果失败,返回-1并设置相应的错误码。 

2.shmctl()

shmctl()函数用于对共享内存进行控制操作,如初始化、删除等,其定义如下:

#include <sys/shm.h>  
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

其中,shmid为共享内存的标识符,由shmget()函数返回;cmd为指定要执行的操作命令。常用的命令有IPC_RMID(删除共享内存段)等;buf为指向shmid_ds结构的指针,用于设置或获取共享内存的属性。

若执行成功,shmctl()函数返回0。如果失败,返回-1。

3.shmat()

 shmat()函数用于将共享内存连接到当前进程的地址空间中。其定义如下:

#include <sys/shm.h>  
void *shmat(int shmid, const void *shmaddr, int shmflg);

其中,shmid为共享内存的标识符,由shmget()函数返回;shmaddr为指定共享内存连接到当前进程的地址空间的起始地址。如果这个参数为NULL,系统会自动选择一个合适的地址;shmflg为指定连接共享内存的权限标志,常用的权限标志有SHM_RDONLY(只读连接)等。

若执行成功shmat()函数返回一个指向共享内存的指针。如果失败,返回(void *) -1。

4.shmdt()

shmdt()函数是用于用于将共享内存从当前进程的地址空间中分离。其定义如下:

#include <sys/shm.h>  
int shmdt(const void *shmaddr);

其中,shmaddr为指定要分离的共享内存的地址。这个地址是由shmat()函数返回的指针。

若执行成功shmdt()函数返回0。如果失败,返回-1并设置相应的错误码。

5.举例

 我将通过使用这四个函数,来实现一个小项目,项目的目的是:创建一个大小为1024字节的共享内存段,将数字0到9转换为字符并存储到该共享内存中,然后从当前进程中打印出该字符串,最后删除共享内存段。

#include <stdio.h>      // 引入标准输入输出库,用于printf函数  
#include <stdlib.h>      // 引入标准库,用于exit函数  
#include <string.h>       // 引入字符串处理库,用于strlen函数  
#include <sys/ipc.h>       // 引入System V IPC库的头文件,用于ftok、shmget、shmat、shmdt和shmctl函数  
#include <sys/shm.h>        // 引入共享内存相关的头文件  
#include <sys/types.h>       // 引入系统类型定义的头文件  
#include <sys/unistd.h>      // 引入POSIX线程库的头文件,虽然这里并未使用到线程相关的功能  
#include <iostream>    // 引入C++标准库,用于iostream类  
  
int main(){    // 主函数入口点  
    int shm;    // 声明一个整型变量shm,用于存储共享内存标识符  
    key_t key;  // 声明一个key_t类型的变量key,用于存储IPC键值  
    key=ftok(".", 'R');  // 使用ftok函数生成一个唯一的IPC键值,'R'是生成键值的字符,"./"是基路径  
    char * buff;  // 声明一个字符指针变量buff,用于存储共享内存的地址  
    shm=shmget(key,1024,0666|IPC_CREAT);  // 使用shmget函数获取或创建一个大小为1024字节的共享内存段,0666是共享内存的权限设置,IPC_CREAT表示如果该共享内存不存在则创建它  
    if(shm<0){    // 检查共享内存是否获取成功,如果失败则输出错误信息并退出程序  
        perror("shmget error");    // 使用perror函数输出错误信息  
        exit(1);    // 使用exit函数退出程序  
    }      
    buff=(char*) shmat(shm,NULL,0);  // 使用shmat函数将共享内存附加到当前进程的地址空间中,NULL参数表示让系统自动选择一个合适的地址,0是shmat函数的标志参数,这里没有使用到该标志位  
    if (buff == (char *) -1) {  // 检查共享内存是否附加成功,如果失败则输出错误信息并退出程序  
        perror("shmat error");  // 使用perror函数输出错误信息  
        exit(1);  // 使用exit函数退出程序  
    }    
    for(int i=0;i<10;i++){  // 使用for循环将数字0到9转换为字符并存储到共享内存中,每个数字占用一个字节的空间,所以这里最多只能存储10个数字字符(包括字符串终止符'\0')  
        buff[i]='0'+i;   // '0'+i将数字i转换为字符存储到buff[i]中,例如i为0时,'0'+0='0',i为1时,'0'+1='1',以此类推。注意这里的字符'0'实际上是数字字符的ASCII码值48。  
    }      
    buff[9] = '\0';  // 在字符串的末尾添加一个'\0'字符,作为字符串的终止符。注意这里的数组下标是从0开始的,所以这里实际上是在存储第11个字符。由于之前已经存储了10个数字字符,所以这里存储'\0'字符后字符串就结束了。如果下标超过数组大小会导致数组越界访问,这是一种常见的编程错误。在实际编程中要特别注意数组下标的范围。  
    printf("%s\n", buff);  // 使用printf函数打印共享内存中的字符串。由于之前在字符串末尾添加了'\0'字符作为终止符,所以这里的printf函数会正确地打印出字符串"0123456789"。注意这里的数组下标是从0开始的,所以这里实际上是在打印第10个字符。如果下标超过数组大小会导致数组越界访问,这是一种常见的编程错误。在实际编程中要特别注意数组下标的范围。另外需要注意的是这里的printf函数是使用标准库中的函数,而不是iostream库中的函数。虽然iostream库也可以用于C++中的输入输出操作,但这里使用的是C语言的标准库函数。在实际编程中要根据需要选择合适的库函数。  
    shmdt(buff);  // 使用shmdt函数将共享内存从当前进程的地址空间中分离出来。
    shmctl(shm,IPC_RMID,NULL);    //shmctl函数删除共享内存段
    return 0;    
}

运行代码得到结果:

linux多进程共享内存_python多进程用不了

今天的文章linux多进程共享内存_python多进程用不了分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/79969.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注