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

📄 shm.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/ipc/shm.c * Copyright (C) 1992, 1993 Krishna Balasubramanian *	 Many improvements/fixes by Bruno Haible. * Replaced `struct shm_desc' by `struct vm_area_struct', July 1994. * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli. * * /proc/sysvipc/shm support (c) 1999 Dragos Acostachioaie <dragos@iname.com> * BIGMEM support, Andrea Arcangeli <andrea@suse.de> * SMP thread shm, Jean-Luc Boyard <jean-luc.boyard@siemens.fr> * HIGHMEM support, Ingo Molnar <mingo@redhat.com> * Make shmmax, shmall, shmmni sysctl'able, Christoph Rohland <cr@sap.com> * Shared /dev/zero support, Kanoj Sarcar <kanoj@sgi.com> * Move the mm functionality over to mm/shmem.c, Christoph Rohland <cr@sap.com> * */#include <linux/config.h>#include <linux/slab.h>#include <linux/shm.h>#include <linux/init.h>#include <linux/file.h>#include <linux/mman.h>#include <linux/proc_fs.h>#include <asm/uaccess.h>#include "util.h"struct shmid_kernel /* private to the kernel */{		struct kern_ipc_perm	shm_perm;	struct file *		shm_file;	int			id;	unsigned long		shm_nattch;	unsigned long		shm_segsz;	time_t			shm_atim;	time_t			shm_dtim;	time_t			shm_ctim;	pid_t			shm_cprid;	pid_t			shm_lprid;};#define shm_flags	shm_perm.modestatic struct file_operations shm_file_operations;static struct vm_operations_struct shm_vm_ops;static struct ipc_ids shm_ids;#define shm_lock(id)	((struct shmid_kernel*)ipc_lock(&shm_ids,id))#define shm_unlock(id)	ipc_unlock(&shm_ids,id)#define shm_lockall()	ipc_lockall(&shm_ids)#define shm_unlockall()	ipc_unlockall(&shm_ids)#define shm_get(id)	((struct shmid_kernel*)ipc_get(&shm_ids,id))#define shm_buildid(id, seq) \	ipc_buildid(&shm_ids, id, seq)static int newseg (key_t key, int shmflg, size_t size);static void shm_open (struct vm_area_struct *shmd);static void shm_close (struct vm_area_struct *shmd);#ifdef CONFIG_PROC_FSstatic int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);#endifsize_t	shm_ctlmax = SHMMAX;size_t 	shm_ctlall = SHMALL;int 	shm_ctlmni = SHMMNI;static int shm_tot; /* total number of shared memory pages */void __init shm_init (void){	ipc_init_ids(&shm_ids, 1);#ifdef CONFIG_PROC_FS	create_proc_read_entry("sysvipc/shm", 0, 0, sysvipc_shm_read_proc, NULL);#endif}static inline int shm_checkid(struct shmid_kernel *s, int id){	if (ipc_checkid(&shm_ids,&s->shm_perm,id))		return -EIDRM;	return 0;}static inline struct shmid_kernel *shm_rmid(int id){	return (struct shmid_kernel *)ipc_rmid(&shm_ids,id);}static inline int shm_addid(struct shmid_kernel *shp){	return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1);}static inline void shm_inc (int id) {	struct shmid_kernel *shp;	if(!(shp = shm_lock(id)))		BUG();	shp->shm_atim = CURRENT_TIME;	shp->shm_lprid = current->pid;	shp->shm_nattch++;	shm_unlock(id);}/* This is called by fork, once for every shm attach. */static void shm_open (struct vm_area_struct *shmd){	shm_inc (shmd->vm_file->f_dentry->d_inode->i_ino);}/* * shm_destroy - free the struct shmid_kernel * * @shp: struct to free * * It has to be called with shp and shm_ids.sem locked */static void shm_destroy (struct shmid_kernel *shp){	shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT;	shm_rmid (shp->id);	shmem_lock(shp->shm_file, 0);	fput (shp->shm_file);	kfree (shp);}/* * remove the attach descriptor shmd. * free memory for segment if it is marked destroyed. * The descriptor has already been removed from the current->mm->mmap list * and will later be kfree()d. */static void shm_close (struct vm_area_struct *shmd){	struct file * file = shmd->vm_file;	int id = file->f_dentry->d_inode->i_ino;	struct shmid_kernel *shp;	down (&shm_ids.sem);	/* remove from the list of attaches of the shm segment */	if(!(shp = shm_lock(id)))		BUG();	shp->shm_lprid = current->pid;	shp->shm_dtim = CURRENT_TIME;	shp->shm_nattch--;	if(shp->shm_nattch == 0 &&	   shp->shm_flags & SHM_DEST)		shm_destroy (shp);	shm_unlock(id);	up (&shm_ids.sem);}static int shm_mmap(struct file * file, struct vm_area_struct * vma){	UPDATE_ATIME(file->f_dentry->d_inode);	vma->vm_ops = &shm_vm_ops;	shm_inc(file->f_dentry->d_inode->i_ino);	return 0;}static struct file_operations shm_file_operations = {	mmap:	shm_mmap};static struct vm_operations_struct shm_vm_ops = {	open:	shm_open,	/* callback for a new vm-area open */	close:	shm_close,	/* callback for when the vm-area is released */	nopage:	shmem_nopage,};static int newseg (key_t key, int shmflg, size_t size){	int error;	struct shmid_kernel *shp;	int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT;	struct file * file;	char name[13];	int id;	if (size < SHMMIN || size > shm_ctlmax)		return -EINVAL;	if (shm_tot + numpages >= shm_ctlall)		return -ENOSPC;	shp = (struct shmid_kernel *) kmalloc (sizeof (*shp), GFP_USER);	if (!shp)		return -ENOMEM;	sprintf (name, "SYSV%08x", key);	file = shmem_file_setup(name, size);	error = PTR_ERR(file);	if (IS_ERR(file))		goto no_file;	error = -ENOSPC;	id = shm_addid(shp);	if(id == -1) 		goto no_id;	shp->shm_perm.key = key;	shp->shm_flags = (shmflg & S_IRWXUGO);	shp->shm_cprid = current->pid;	shp->shm_lprid = 0;	shp->shm_atim = shp->shm_dtim = 0;	shp->shm_ctim = CURRENT_TIME;	shp->shm_segsz = size;	shp->shm_nattch = 0;	shp->id = shm_buildid(id,shp->shm_perm.seq);	shp->shm_file = file;	file->f_dentry->d_inode->i_ino = shp->id;	file->f_op = &shm_file_operations;	shm_tot += numpages;	shm_unlock (id);	return shp->id;no_id:	fput(file);no_file:	kfree(shp);	return error;}asmlinkage long sys_shmget (key_t key, size_t size, int shmflg){	struct shmid_kernel *shp;	int err, id = 0;	down(&shm_ids.sem);	if (key == IPC_PRIVATE) {		err = newseg(key, shmflg, size);	} else if ((id = ipc_findkey(&shm_ids, key)) == -1) {		if (!(shmflg & IPC_CREAT))			err = -ENOENT;		else			err = newseg(key, shmflg, size);	} else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) {		err = -EEXIST;	} else {		shp = shm_lock(id);		if(shp==NULL)			BUG();		if (shp->shm_segsz < size)			err = -EINVAL;		else if (ipcperms(&shp->shm_perm, shmflg))			err = -EACCES;		else			err = shm_buildid(id, shp->shm_perm.seq);		shm_unlock(id);	}	up(&shm_ids.sem);	return err;}static inline unsigned long copy_shmid_to_user(void *buf, struct shmid64_ds *in, int version){	switch(version) {	case IPC_64:		return copy_to_user(buf, in, sizeof(*in));	case IPC_OLD:	    {		struct shmid_ds out;		ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm);		out.shm_segsz	= in->shm_segsz;		out.shm_atime	= in->shm_atime;		out.shm_dtime	= in->shm_dtime;		out.shm_ctime	= in->shm_ctime;		out.shm_cpid	= in->shm_cpid;		out.shm_lpid	= in->shm_lpid;		out.shm_nattch	= in->shm_nattch;		return copy_to_user(buf, &out, sizeof(out));	    }	default:		return -EINVAL;	}}struct shm_setbuf {	uid_t	uid;	gid_t	gid;	mode_t	mode;};	static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void *buf, int version){	switch(version) {	case IPC_64:	    {		struct shmid64_ds tbuf;		if (copy_from_user(&tbuf, buf, sizeof(tbuf)))			return -EFAULT;		out->uid	= tbuf.shm_perm.uid;		out->gid	= tbuf.shm_perm.gid;		out->mode	= tbuf.shm_flags;		return 0;	    }	case IPC_OLD:	    {		struct shmid_ds tbuf_old;		if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))			return -EFAULT;		out->uid	= tbuf_old.shm_perm.uid;		out->gid	= tbuf_old.shm_perm.gid;		out->mode	= tbuf_old.shm_flags;		return 0;	    }	default:		return -EINVAL;	}}static inline unsigned long copy_shminfo_to_user(void *buf, struct shminfo64 *in, int version){	switch(version) {	case IPC_64:		return copy_to_user(buf, in, sizeof(*in));	case IPC_OLD:	    {		struct shminfo out;		if(in->shmmax > INT_MAX)			out.shmmax = INT_MAX;		else			out.shmmax = (int)in->shmmax;		out.shmmin	= in->shmmin;		out.shmmni	= in->shmmni;		out.shmseg	= in->shmseg;		out.shmall	= in->shmall; 		return copy_to_user(buf, &out, sizeof(out));	    }	default:		return -EINVAL;	}}static void shm_get_stat (unsigned long *rss, unsigned long *swp) {	struct shmem_inode_info *info;	int i;	*rss = 0;	*swp = 0;	for(i = 0; i <= shm_ids.max_id; i++) {		struct shmid_kernel* shp;		struct inode * inode;		shp = shm_get(i);		if(shp == NULL)			continue;		inode = shp->shm_file->f_dentry->d_inode;		info = SHMEM_I(inode);		spin_lock (&info->lock);		*rss += inode->i_mapping->nrpages;		*swp += info->swapped;		spin_unlock (&info->lock);	}}asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf){

⌨️ 快捷键说明

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