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

📄 shm.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct shm_setbuf setbuf;	struct shmid_kernel *shp;	int err, version;	if (cmd < 0 || shmid < 0)		return -EINVAL;	version = ipc_parse_version(&cmd);	switch (cmd) { /* replace with proc interface ? */	case IPC_INFO:	{		struct shminfo64 shminfo;		memset(&shminfo,0,sizeof(shminfo));		shminfo.shmmni = shminfo.shmseg = shm_ctlmni;		shminfo.shmmax = shm_ctlmax;		shminfo.shmall = shm_ctlall;		shminfo.shmmin = SHMMIN;		if(copy_shminfo_to_user (buf, &shminfo, version))			return -EFAULT;		/* reading a integer is always atomic */		err= shm_ids.max_id;		if(err<0)			err = 0;		return err;	}	case SHM_INFO:	{		struct shm_info shm_info;		memset(&shm_info,0,sizeof(shm_info));		down(&shm_ids.sem);		shm_lockall();		shm_info.used_ids = shm_ids.in_use;		shm_get_stat (&shm_info.shm_rss, &shm_info.shm_swp);		shm_info.shm_tot = shm_tot;		shm_info.swap_attempts = 0;		shm_info.swap_successes = 0;		err = shm_ids.max_id;		shm_unlockall();		up(&shm_ids.sem);		if(copy_to_user (buf, &shm_info, sizeof(shm_info)))			return -EFAULT;		return err < 0 ? 0 : err;	}	case SHM_STAT:	case IPC_STAT:	{		struct shmid64_ds tbuf;		int result;		memset(&tbuf, 0, sizeof(tbuf));		shp = shm_lock(shmid);		if(shp==NULL)			return -EINVAL;		if(cmd==SHM_STAT) {			err = -EINVAL;			if (shmid > shm_ids.max_id)				goto out_unlock;			result = shm_buildid(shmid, shp->shm_perm.seq);		} else {			err = shm_checkid(shp,shmid);			if(err)				goto out_unlock;			result = 0;		}		err=-EACCES;		if (ipcperms (&shp->shm_perm, S_IRUGO))			goto out_unlock;		kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);		tbuf.shm_segsz	= shp->shm_segsz;		tbuf.shm_atime	= shp->shm_atim;		tbuf.shm_dtime	= shp->shm_dtim;		tbuf.shm_ctime	= shp->shm_ctim;		tbuf.shm_cpid	= shp->shm_cprid;		tbuf.shm_lpid	= shp->shm_lprid;		tbuf.shm_nattch	= shp->shm_nattch;		shm_unlock(shmid);		if(copy_shmid_to_user (buf, &tbuf, version))			return -EFAULT;		return result;	}	case SHM_LOCK:	case SHM_UNLOCK:	{/* Allow superuser to lock segment in memory *//* Should the pages be faulted in here or leave it to user? *//* need to determine interaction with current->swappable */		if (!capable(CAP_IPC_LOCK))			return -EPERM;		shp = shm_lock(shmid);		if(shp==NULL)			return -EINVAL;		err = shm_checkid(shp,shmid);		if(err)			goto out_unlock;		if(cmd==SHM_LOCK) {			shmem_lock(shp->shm_file, 1);			shp->shm_flags |= SHM_LOCKED;		} else {			shmem_lock(shp->shm_file, 0);			shp->shm_flags &= ~SHM_LOCKED;		}		shm_unlock(shmid);		return err;	}	case IPC_RMID:	{		/*		 *	We cannot simply remove the file. The SVID states		 *	that the block remains until the last person		 *	detaches from it, then is deleted. A shmat() on		 *	an RMID segment is legal in older Linux and if 		 *	we change it apps break...		 *		 *	Instead we set a destroyed flag, and then blow		 *	the name away when the usage hits zero.		 */		down(&shm_ids.sem);		shp = shm_lock(shmid);		err = -EINVAL;		if (shp == NULL) 			goto out_up;		err = shm_checkid(shp, shmid);		if(err)			goto out_unlock_up;		if (current->euid != shp->shm_perm.uid &&		    current->euid != shp->shm_perm.cuid && 		    !capable(CAP_SYS_ADMIN)) {			err=-EPERM;			goto out_unlock_up;		}		if (shp->shm_nattch){			shp->shm_flags |= SHM_DEST;			/* Do not find it any more */			shp->shm_perm.key = IPC_PRIVATE;		} else			shm_destroy (shp);		/* Unlock */		shm_unlock(shmid);		up(&shm_ids.sem);		return err;	}	case IPC_SET:	{		if(copy_shmid_from_user (&setbuf, buf, version))			return -EFAULT;		down(&shm_ids.sem);		shp = shm_lock(shmid);		err=-EINVAL;		if(shp==NULL)			goto out_up;		err = shm_checkid(shp,shmid);		if(err)			goto out_unlock_up;		err=-EPERM;		if (current->euid != shp->shm_perm.uid &&		    current->euid != shp->shm_perm.cuid && 		    !capable(CAP_SYS_ADMIN)) {			goto out_unlock_up;		}		shp->shm_perm.uid = setbuf.uid;		shp->shm_perm.gid = setbuf.gid;		shp->shm_flags = (shp->shm_flags & ~S_IRWXUGO)			| (setbuf.mode & S_IRWXUGO);		shp->shm_ctim = CURRENT_TIME;		break;	}	default:		return -EINVAL;	}	err = 0;out_unlock_up:	shm_unlock(shmid);out_up:	up(&shm_ids.sem);	return err;out_unlock:	shm_unlock(shmid);	return err;}/* * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists. */asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr){	struct shmid_kernel *shp;	unsigned long addr;	unsigned long size;	struct file * file;	int    err;	unsigned long flags;	unsigned long prot;	unsigned long o_flags;	int acc_mode;	void *user_addr;	if (shmid < 0)		return -EINVAL;	if ((addr = (ulong)shmaddr)) {		if (addr & (SHMLBA-1)) {			if (shmflg & SHM_RND)				addr &= ~(SHMLBA-1);	   /* round down */			else				return -EINVAL;		}		flags = MAP_SHARED | MAP_FIXED;	} else {		if ((shmflg & SHM_REMAP))			return -EINVAL;		flags = MAP_SHARED;	}	if (shmflg & SHM_RDONLY) {		prot = PROT_READ;		o_flags = O_RDONLY;		acc_mode = S_IRUGO;	} else {		prot = PROT_READ | PROT_WRITE;		o_flags = O_RDWR;		acc_mode = S_IRUGO | S_IWUGO;	}	/*	 * We cannot rely on the fs check since SYSV IPC does have an	 * additional creator id...	 */	shp = shm_lock(shmid);	if(shp == NULL)		return -EINVAL;	err = shm_checkid(shp,shmid);	if (err) {		shm_unlock(shmid);		return err;	}	if (ipcperms(&shp->shm_perm, acc_mode)) {		shm_unlock(shmid);		return -EACCES;	}	file = shp->shm_file;	size = file->f_dentry->d_inode->i_size;	shp->shm_nattch++;	shm_unlock(shmid);	down_write(&current->mm->mmap_sem);	if (addr && !(shmflg & SHM_REMAP)) {		user_addr = ERR_PTR(-EINVAL);		if (find_vma_intersection(current->mm, addr, addr + size))			goto invalid;		/*		 * If shm segment goes below stack, make sure there is some		 * space left for the stack to grow (at least 4 pages).		 */		if (addr < current->mm->start_stack &&		    addr > current->mm->start_stack - size - PAGE_SIZE * 5)			goto invalid;	}			user_addr = (void*) do_mmap (file, addr, size, prot, flags, 0);invalid:	up_write(&current->mm->mmap_sem);	down (&shm_ids.sem);	if(!(shp = shm_lock(shmid)))		BUG();	shp->shm_nattch--;	if(shp->shm_nattch == 0 &&	   shp->shm_flags & SHM_DEST)		shm_destroy (shp);	shm_unlock(shmid);	up (&shm_ids.sem);	*raddr = (unsigned long) user_addr;	err = 0;	if (IS_ERR(user_addr))		err = PTR_ERR(user_addr);	return err;}/* * detach and kill segment if marked destroyed. * The work is done in shm_close. */asmlinkage long sys_shmdt (char *shmaddr){	struct mm_struct *mm = current->mm;	struct vm_area_struct *shmd, *shmdnext;	down_write(&mm->mmap_sem);	for (shmd = mm->mmap; shmd; shmd = shmdnext) {		shmdnext = shmd->vm_next;		if (shmd->vm_ops == &shm_vm_ops		    && shmd->vm_start - (shmd->vm_pgoff << PAGE_SHIFT) == (ulong) shmaddr)			do_munmap(mm, shmd->vm_start, shmd->vm_end - shmd->vm_start);	}	up_write(&mm->mmap_sem);	return 0;}#ifdef CONFIG_PROC_FSstatic int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data){	off_t pos = 0;	off_t begin = 0;	int i, len = 0;	down(&shm_ids.sem);	len += sprintf(buffer, "       key      shmid perms       size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime\n");	for(i = 0; i <= shm_ids.max_id; i++) {		struct shmid_kernel* shp;		shp = shm_lock(i);		if(shp!=NULL) {#define SMALL_STRING "%10d %10d  %4o %10u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"#define BIG_STRING   "%10d %10d  %4o %21u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"			char *format;			if (sizeof(size_t) <= sizeof(int))				format = SMALL_STRING;			else				format = BIG_STRING;			len += sprintf(buffer + len, format,				shp->shm_perm.key,				shm_buildid(i, shp->shm_perm.seq),				shp->shm_flags,				shp->shm_segsz,				shp->shm_cprid,				shp->shm_lprid,				shp->shm_nattch,				shp->shm_perm.uid,				shp->shm_perm.gid,				shp->shm_perm.cuid,				shp->shm_perm.cgid,				shp->shm_atim,				shp->shm_dtim,				shp->shm_ctim);			shm_unlock(i);			pos += len;			if(pos < offset) {				len = 0;				begin = pos;			}			if(pos > offset + length)				goto done;		}	}	*eof = 1;done:	up(&shm_ids.sem);	*start = buffer + (offset - begin);	len -= (offset - begin);	if(len > length)		len = length;	if(len < 0)		len = 0;	return len;}#endif

⌨️ 快捷键说明

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