undefined symbol _shmget referenced from text segment
时间: 2023-12-03 13:46:16 浏览: 31
这个错误通常是因为缺少共享内存库文件所致。共享内存是一个用于在进程之间共享数据的系统资源,它可以提高程序的性能。在 Linux 系统上,共享内存库文件通常是 librt.so,您可以尝试安装它来解决此问题。
您可以使用以下命令安装共享内存库文件:
```sh
sudo apt-get update
sudo apt-get install librt-dev
```
如果您使用的是其他 Linux 发行版,可以使用相应的包管理器来安装 librt 库文件。
如果安装 librt 库文件后仍然出现此错误,请确保您的代码中包含了正确的头文件,并且在编译时链接了正确的库文件。
相关问题
shm_open shmget
`shm_open()` 和 `shmget()` 都是用于共享内存的函数,但是它们是针对不同的操作系统。
`shm_open()` 是在类 UNIX 操作系统中使用的函数,用于打开一个具有一定名字的共享内存对象,并返回一个文件描述符。开发者可以使用这个文件描述符来访问共享内存对象。`shm_open()` 函数的原型如下:
```c
#include <sys/mman.h>
int shm_open(const char *name, int oflag, mode_t mode);
```
`shmget()` 是在 Linux 操作系统中使用的函数,用于创建一个具有一定 key 值的共享内存区域,并返回一个标识符(即 shmid)。开发者可以使用这个 shmid 来访问共享内存区域。`shmget()` 函数的原型如下:
```c
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
```
两个函数都是为了实现进程间通信而设计的,但是它们的使用方法和参数有所不同。在使用共享内存之前,开发者需要先明确自己的操作系统是哪个,然后再选择相应的函数来实现共享内存的功能。
此应用程序执行到最后会出现错误提示“trying to free free page”,这是由于sys_shmget函数在 使用get_free_page函数申请到一个物理页时,将此物理页在mem_map中记录的引用计数设置为1,而再次调 用sys_shmget函数使用key从vector中获取共享的物理页时,没有增加此物理页在mem_map中的引用计数。 所以,当生产者进程和消费者进程退出时,都会调用free_page函数释放此物理页,每调用一次就会将 mem_map中的引用计数减1,导致一个物理页的引用计数被减为了负数,这是Linux物理页管理程序所不允许 的,所以执行了mm/memory.c中free_page函数的最后一行(第310行)代码打印出错信息。请读者改进 sys_shmget函数,当能够使用key从vector中获取共享的物理页时,将此物理页在mem_map中的引用计数增 加1该如何修改。
可以在sys_shmget函数中找到使用get_free_page函数申请到一个物理页的代码,在此代码后面添加mem_map引用计数增加的代码即可。具体实现如下:
```C
unsigned long sys_shmget(key_t key, size_t size, int shmflg)
{
struct shmid_ds *buf;
struct shminfo *inf;
struct shm_file_data *shm_file;
struct page *page;
unsigned long addr;
int shmid, err, temp;
int i;
down(&shm_ids.sem);
// 查找 key 对应的共享内存是否已经存在
for (i = 0; i < SHM_NR; i++) {
if (shm_ids.used_ids[i] &&
shm_ids.shm_file[i]->key == key) {
shm_file = shm_ids.shm_file[i];
break;
}
}
// 如果 key 对应的共享内存不存在,就创建一个新的共享内存
if (i == SHM_NR) {
if (!(shmflg & IPC_CREAT)) { // 如果没有创建新的共享内存的权限
up(&shm_ids.sem);
return -EINVAL;
}
// 查找一个空闲的共享内存结构体
for (i = 0; i < SHM_NR; i++) {
if (!shm_ids.used_ids[i]) {
shm_file = kmalloc(sizeof(struct shm_file_data), GFP_KERNEL);
if (!shm_file) {
up(&shm_ids.sem);
return -ENOMEM;
}
// 申请一个物理页
page = get_free_page();
if (!page) {
up(&shm_ids.sem);
kfree(shm_file);
return -ENOMEM;
}
// 将物理页映射到内核空间
addr = (unsigned long) page_address(page);
if (!addr) {
up(&shm_ids.sem);
free_page((unsigned long) page);
kfree(shm_file);
return -ENOMEM;
}
// 初始化共享内存结构体
shm_file->key = key;
shm_file->page = page;
shm_file->attached = 0;
// 将共享内存结构体添加到 vector 中
temp = find_empty_slot();
if (temp == -1) {
up(&shm_ids.sem);
free_page((unsigned long) page);
kfree(shm_file);
return -EINVAL;
}
shm_ids.used_ids[temp] = 1;
shm_ids.shm_file[temp] = shm_file;
// 设置物理页在 mem_map 中的引用计数
atomic_inc(&mem_map[MAP_NR(page->phys_addr)].count);
buf = (struct shmid_ds *) getname(kernel_stack, (char *) arg2);
if (!buf) {
up(&shm_ids.sem);
free_page((unsigned long) page);
kfree(shm_file);
return -EFAULT;
}
// 初始化共享内存的元信息
buf->shm_nattch = 0;
buf->shm_page = page;
buf->shm_segsz = PAGE_SIZE;
putname((char *) arg2);
up(&shm_ids.sem);
return temp;
}
}
up(&shm_ids.sem);
return -EINVAL;
}
// 如果 key 对应的共享内存已经存在,就返回共享内存的编号
shmid = i;
shm_file = shm_ids.shm_file[shmid];
// 设置物理页在 mem_map 中的引用计数
atomic_inc(&mem_map[MAP_NR(shm_file->page->phys_addr)].count);
up(&shm_ids.sem);
return shmid;
}
```
在上述代码中,我们在申请到物理页后,添加了以下代码:
```C
// 设置物理页在 mem_map 中的引用计数
atomic_inc(&mem_map[MAP_NR(page->phys_addr)].count);
```
这样,在使用key从vector中获取共享的物理页时,就会增加此物理页在mem_map中的引用计数,从而避免了引用计数被减为负数的问题。