⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtai_shm.c

📁 Linux共享内存share memory通信机制的内核实现
💻 C
字号:
/*COPYRIGHT (C) 1999  Paolo Mantegazza (mantegazza@aero.polimi.it)This library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.*/#define RTAI_SHM_MISC_MINOR  254 // The same minor used to mknod for major 10.#define MAX_SLOTS            32  // Set it according to your needs.#define MAX_OWNERS           4*MAX_SLOTS // avrg 4 simultaneous users per slot!#include <linux/version.h>#include <linux/module.h>#include <linux/config.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/fcntl.h>#include <linux/mm.h>#include <linux/miscdevice.h>#include <linux/malloc.h>#include <linux/wrapper.h>#include <asm/uaccess.h>#include <asm/pgtable.h>#include <asm/io.h>#include "rtai_shm.h"#include "kvmem.h"/* The two lines below could go into a structure. It is preferred   to keep them distinct to recall that a vmarea pertains only to    processes allocated/mmaped areas, and not to module ones. */static unsigned long long name_pid_list[MAX_OWNERS + 1] = { 0LL, };static struct vm_area_struct *vmarea[MAX_OWNERS + 1]   = { 0, };static struct { void *adr; unsigned long name, size, count; } shm_list[MAX_SLOTS + 1] = { {0, 0, 0, 0}, };static spinlock_t shm_lock = SPIN_LOCK_UNLOCKED;#define NAME(x) ((unsigned long *)(&(x)))[0]#define PID(x)  ((unsigned long *)(&(x)))[1]static inline int registr(unsigned long long name_pid){	int owner;	for (owner = 1; owner <= MAX_OWNERS; owner++) {		if (!name_pid_list[owner]) {			name_pid_list[owner] = name_pid;			vmarea[owner] = (struct vm_area_struct *)(PID(name_pid) | 0xF0000000);			return owner;		}	}	return 0;} static inline int deregistr(unsigned long long name_pid){	int owner;	for (owner = 1; owner <= MAX_OWNERS; owner++) {		if (name_pid_list[owner] == name_pid) {			name_pid_list[owner] = 0LL;			vmarea[owner] = 0;			return owner;		}	}	return 0;} static inline int there_is_not_and_reg(unsigned long long name_pid){	int owner;	for (owner = 1; owner <= MAX_OWNERS; owner++) {		if (name_pid_list[owner] == name_pid) {			return 0;		}	}	return registr(name_pid);} static inline int find_name(unsigned long name){	int slot;	for (slot = 1; slot <= MAX_SLOTS; slot++) {		if (shm_list[slot].name == name) {			return slot;		}	}	return 0;} static inline int find_name_and_reg(unsigned long name, unsigned long pid){	int slot;	unsigned long long name_pid;	for (slot = 1; slot <= MAX_SLOTS; slot++) {		if (shm_list[slot].name == name) {			NAME(name_pid) = name;			PID(name_pid)  = pid;			return there_is_not_and_reg(name_pid) ? slot : 0;		}	}	return 0;} static inline int find_free_slot_and_reg(unsigned long name, unsigned long pid){	int slot;	unsigned long long name_pid;	for (slot = 1; slot <= MAX_SLOTS; slot++) {		if (!shm_list[slot].name) {			NAME(name_pid) = name;			PID(name_pid)  = pid;			return there_is_not_and_reg(name_pid) ? slot : 0;		}	}	return 0;} static inline int find_name_and_drg(unsigned long name, unsigned long pid){	int slot;	unsigned long long name_pid;	for (slot = 1; slot <= MAX_SLOTS; slot++) {		if (shm_list[slot].name == name) {			NAME(name_pid) = name;			PID(name_pid)  = pid;			return deregistr(name_pid) ? slot : 0;		}	}	return 0;} void *rtai_kmalloc_f(int name, int size, unsigned long pid){	unsigned long flags;	void *adr;	int slot;	if (size <= 0) {		return 0;	}	spin_lock_irqsave(&shm_lock, flags);	if ((slot = find_name_and_reg(name, pid))) {		shm_list[slot].count++;		MOD_INC_USE_COUNT;		adr = shm_list[slot].adr;		spin_unlock_irqrestore(&shm_lock, flags);		return adr;	}	spin_unlock_irqrestore(&shm_lock, flags);	size = REAL_SIZE(size);	if ((adr = rvmalloc(size))) {		spin_lock_irqsave(&shm_lock, flags);		if ((slot = find_free_slot_and_reg(name, pid))) {			memset(adr, 0, size);			shm_list[slot].name  = name;			shm_list[slot].adr   = adr;			shm_list[slot].size  = size;			shm_list[slot].count = 1;			MOD_INC_USE_COUNT;			spin_unlock_irqrestore(&shm_lock, flags);			return adr;		}		spin_unlock_irqrestore(&shm_lock, flags);		rvfree(adr, size);	}	return 0;}void rtai_kfree_f(int name, unsigned long pid){	unsigned long flags;	int slot, size;	void *adr;	spin_lock_irqsave(&shm_lock, flags);	if ((slot = find_name_and_drg(name, pid))) {		MOD_DEC_USE_COUNT;		if (!(--shm_list[slot].count)) {			adr  = shm_list[slot].adr;			size = shm_list[slot].size;			shm_list[slot] = shm_list[0];			spin_unlock_irqrestore(&shm_lock, flags);			rvfree(adr, size);			return;		}	}	spin_unlock_irqrestore(&shm_lock, flags);	return;}int rtai_shm_ioctl(struct inode *inode, struct file *file, unsigned int srq, unsigned long name){	static void rtai_shm_vm_close(struct vm_area_struct *vma);	int owner, slot;	long long name_pid;	switch (srq) {		case 1:			if (rtai_kmalloc_f(((unsigned long *)name)[0], ((unsigned long *)name)[1], current->pid)) {				return shm_list[find_name(((unsigned long *)name)[0])].size;			}			return 0;		case 2:			NAME(name_pid) = name;			PID(name_pid)  = current->pid;			for (owner = 1; owner <= MAX_OWNERS; owner++) {				if (name_pid_list[owner] == name_pid) {					if (vmarea[owner] && (vmarea[owner]->vm_ops)->close == rtai_shm_vm_close) {						vmarea[owner]->vm_ops = 0;						if ((slot = find_name(name))) {							return shm_list[slot].size;						}					}					printk("VMAREA NOT FOUND FOR AN EXISTING NAME_PID AT UNMAP REQUEST.\n");					return 0;				}			}			return 0;		case 3:			rtai_kfree_f(name, current->pid);			return 0;	}	return 0;}static void rtai_shm_vm_close(struct vm_area_struct *vma){	int owner, slot;	for (owner = 1; owner <= MAX_OWNERS; owner++) {		if (vmarea[owner] == vma && PID(name_pid_list[owner]) == current->pid) {			if((slot = find_name(NAME(name_pid_list[owner])))) {				if (shm_list[slot].count == 1) {					printk("DELETING AREA %lx AT KERNEL REQUEST.\n", shm_list[slot].name);				} else {					printk("UNMAPPING AREA %lx AT KERNEL REQUEST.\n", shm_list[slot].name);				}				rtai_kfree_f(shm_list[slot].name, current->pid);				return;			}			printk("NO AREA NAME FOUND FOR AN EXISTING PID_VMA AT KERNEL UNMAP REQUEST.\n");			return;		}	}	printk("NO PID_VMA FOUND AT KERNEL UNMAP REQUEST.\n");	return;}struct vm_operations_struct rtai_shm_vm_ops = { close: rtai_shm_vm_close } ;static int rtai_shm_mmap(struct file *file, struct vm_area_struct *vma){	int owner, slot;	for (owner = 1; owner <= MAX_OWNERS; owner++) {		if (PID(name_pid_list[owner]) == current->pid && vmarea[owner] == ((struct vm_area_struct *)(current->pid | 0xF0000000))) {			if((slot = find_name(NAME(name_pid_list[owner])))) {				vmarea[owner] = vma;				if(!vma->vm_ops) {					vma->vm_ops = &rtai_shm_vm_ops;				}				return rvmmap(shm_list[slot].adr, shm_list[slot].size, vma); 			}			printk("NO AREA NAME FOUND FOR A MAPPABLE PID AT MMAPP REQUEST.\n");			return -EFAULT;		}	}	printk("NO MAPPABLE PID FOUND AT MMAPP REQUEST.\n");	return -EFAULT;}static int rtai_shm_f_open(struct inode *inode, struct file *file){	return 0;}static int rtai_shm_f_close(struct inode *inode, struct file *file){	return 0;}static struct file_operations rtai_shm_fops = 	{ ioctl: rtai_shm_ioctl, mmap: rtai_shm_mmap, open: rtai_shm_f_open, release: rtai_shm_f_close };static struct miscdevice rtai_shm_dev = 	{ RTAI_SHM_MISC_MINOR, "RTAI_SHM", &rtai_shm_fops, NULL, NULL };int init_module (void){	if (misc_register(&rtai_shm_dev) < 0) {		printk("***** COULD NOT REGISTER SHARED MEMORY DEVICE *****\n");		return -EBUSY;	}	return 0 ;}void cleanup_module (void){	int i;	printk("\n");	for (i = 1; i <= MAX_SLOTS; i++) {		if (shm_list[i].name) {			printk("***** FREEING AREA %lx AT MODULE CLEANUP *****\n", shm_list[i].name);			rvfree(shm_list[i].adr, shm_list[i].size);		}	}	printk("\n");	misc_deregister(&rtai_shm_dev);	return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -