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

📄 msg.c

📁 linux1.1源代码
💻 C
字号:
/* * linux/ipc/msg.c * Copyright (C) 1992 Krishna Balasubramanian  */#include <linux/errno.h>#include <linux/sched.h>#include <linux/msg.h>#include <linux/stat.h>#include <linux/malloc.h>#include <asm/segment.h>extern int ipcperms (struct ipc_perm *ipcp, short msgflg);static void freeque (int id);static int newque (key_t key, int msgflg);static int findkey (key_t key);static struct msqid_ds *msgque[MSGMNI];static int msgbytes = 0;static int msghdrs = 0;static unsigned short msg_seq = 0;static int used_queues = 0;static int max_msqid = 0;static struct wait_queue *msg_lock = NULL;void msg_init (void){	int id;		for (id=0; id < MSGMNI; id++) 		msgque[id] = (struct msqid_ds *) IPC_UNUSED;	msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0;	msg_lock = NULL;	return;}int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg){	int id, err;	struct msqid_ds *msq;	struct ipc_perm *ipcp;	struct msg *msgh;	long mtype;		if (msgsz > MSGMAX || msgsz < 0 || msqid < 0)		return -EINVAL;	if (!msgp) 		return -EFAULT;	err = verify_area (VERIFY_READ, msgp->mtext, msgsz);	if (err) 		return err;	if ((mtype = get_fs_long (&msgp->mtype)) < 1)		return -EINVAL;	id = msqid % MSGMNI;	msq = msgque [id];	if (msq == IPC_UNUSED || msq == IPC_NOID)		return -EINVAL;	ipcp = &msq->msg_perm;  slept:	if (ipcp->seq != (msqid / MSGMNI)) 		return -EIDRM;	if (ipcperms(ipcp, S_IWUGO)) 		return -EACCES;		if (msgsz + msq->msg_cbytes > msq->msg_qbytes) { 		/* no space in queue */		if (msgflg & IPC_NOWAIT)			return -EAGAIN;		if (current->signal & ~current->blocked)			return -EINTR;		interruptible_sleep_on (&msq->wwait);		goto slept;	}		/* allocate message header and text space*/ 	msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_USER);	if (!msgh)		return -ENOMEM;	msgh->msg_spot = (char *) (msgh + 1);	memcpy_fromfs (msgh->msg_spot, msgp->mtext, msgsz); 		if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID		|| ipcp->seq != msqid / MSGMNI) {		kfree_s (msgh, sizeof(*msgh) + msgsz);		return -EIDRM;	}	msgh->msg_next = NULL;	if (!msq->msg_first)		msq->msg_first = msq->msg_last = msgh;	else {		msq->msg_last->msg_next = msgh;		msq->msg_last = msgh;	}	msgh->msg_ts = msgsz;	msgh->msg_type = mtype;	msq->msg_cbytes += msgsz;	msgbytes  += msgsz;	msghdrs++;	msq->msg_qnum++;	msq->msg_lspid = current->pid;	msq->msg_stime = CURRENT_TIME;	if (msq->rwait)		wake_up (&msq->rwait);	return msgsz;}int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, 		int msgflg){	struct msqid_ds *msq;	struct ipc_perm *ipcp;	struct msg *tmsg, *leastp = NULL;	struct msg *nmsg = NULL;	int id, err;	if (msqid < 0 || msgsz < 0)		return -EINVAL;	if (!msgp || !msgp->mtext)	    return -EFAULT;	err = verify_area (VERIFY_WRITE, msgp->mtext, msgsz);	if (err)		return err;	id = msqid % MSGMNI;	msq = msgque [id];	if (msq == IPC_NOID || msq == IPC_UNUSED)		return -EINVAL;	ipcp = &msq->msg_perm; 	/* 	 *  find message of correct type.	 *  msgtyp = 0 => get first.	 *  msgtyp > 0 => get first message of matching type.	 *  msgtyp < 0 => get message with least type must be < abs(msgtype).  	 */	while (!nmsg) {		if(ipcp->seq != msqid / MSGMNI)			return -EIDRM;		if (ipcperms (ipcp, S_IRUGO))			return -EACCES;		if (msgtyp == 0) 			nmsg = msq->msg_first;		else if (msgtyp > 0) {			if (msgflg & MSG_EXCEPT) { 				for (tmsg = msq->msg_first; tmsg; 				     tmsg = tmsg->msg_next)					if (tmsg->msg_type != msgtyp)						break;				nmsg = tmsg;			} else {				for (tmsg = msq->msg_first; tmsg; 				     tmsg = tmsg->msg_next)					if (tmsg->msg_type == msgtyp)						break;				nmsg = tmsg;			}		} else {			for (leastp = tmsg = msq->msg_first; tmsg; 			     tmsg = tmsg->msg_next) 				if (tmsg->msg_type < leastp->msg_type) 					leastp = tmsg;			if (leastp && leastp->msg_type <= - msgtyp)				nmsg = leastp;		}				if (nmsg) { /* done finding a message */			if ((msgsz < nmsg->msg_ts) && !(msgflg & MSG_NOERROR))				return -E2BIG;			msgsz = (msgsz > nmsg->msg_ts)? nmsg->msg_ts : msgsz;			if (nmsg ==  msq->msg_first)				msq->msg_first = nmsg->msg_next;			else {				for (tmsg= msq->msg_first; tmsg; 				     tmsg = tmsg->msg_next)					if (tmsg->msg_next == nmsg) 						break;				tmsg->msg_next = nmsg->msg_next;				if (nmsg == msq->msg_last)					msq->msg_last = tmsg;			}			if (!(--msq->msg_qnum))				msq->msg_last = msq->msg_first = NULL;						msq->msg_rtime = CURRENT_TIME;			msq->msg_lrpid = current->pid;			msgbytes -= nmsg->msg_ts; 			msghdrs--; 			msq->msg_cbytes -= nmsg->msg_ts;			if (msq->wwait)				wake_up (&msq->wwait);			put_fs_long (nmsg->msg_type, &msgp->mtype);			memcpy_tofs (msgp->mtext, nmsg->msg_spot, msgsz);			kfree_s (nmsg, sizeof(*nmsg) + msgsz); 			return msgsz;		} else {  /* did not find a message */			if (msgflg & IPC_NOWAIT)				return -ENOMSG;			if (current->signal & ~current->blocked)				return -EINTR; 			interruptible_sleep_on (&msq->rwait);		}	} /* end while */	return -1;}static int findkey (key_t key){	int id;	struct msqid_ds *msq;		for (id=0; id <= max_msqid; id++) {		while ((msq = msgque[id]) == IPC_NOID) 			interruptible_sleep_on (&msg_lock);		if (msq == IPC_UNUSED)			continue;		if (key == msq->msg_perm.key)			return id;	}	return -1;}static int newque (key_t key, int msgflg){	int id;	struct msqid_ds *msq;	struct ipc_perm *ipcp;	for (id=0; id < MSGMNI; id++) 		if (msgque[id] == IPC_UNUSED) {			msgque[id] = (struct msqid_ds *) IPC_NOID;			goto found;		}	return -ENOSPC;found:	msq = (struct msqid_ds *) kmalloc (sizeof (*msq), GFP_KERNEL);	if (!msq) {		msgque[id] = (struct msqid_ds *) IPC_UNUSED;		if (msg_lock)			wake_up (&msg_lock);		return -ENOMEM;	}	ipcp = &msq->msg_perm;	ipcp->mode = (msgflg & S_IRWXUGO);	ipcp->key = key;	ipcp->cuid = ipcp->uid = current->euid;	ipcp->gid = ipcp->cgid = current->egid;	ipcp->seq = msg_seq;	msq->msg_first = msq->msg_last = NULL;	msq->rwait = msq->wwait = NULL;	msq->msg_cbytes = msq->msg_qnum = 0;	msq->msg_lspid = msq->msg_lrpid = 0;	msq->msg_stime = msq->msg_rtime = 0;	msq->msg_qbytes = MSGMNB;	msq->msg_ctime = CURRENT_TIME;	if (id > max_msqid)		max_msqid = id;	msgque[id] = msq;	used_queues++;	if (msg_lock)		wake_up (&msg_lock);	return (int) msg_seq * MSGMNI + id;}int sys_msgget (key_t key, int msgflg){	int id;	struct msqid_ds *msq;		if (key == IPC_PRIVATE) 		return newque(key, msgflg);	if ((id = findkey (key)) == -1) { /* key not used */		if (!(msgflg & IPC_CREAT))			return -ENOENT;		return newque(key, msgflg);	}	if (msgflg & IPC_CREAT && msgflg & IPC_EXCL)		return -EEXIST;	msq = msgque[id];	if (msq == IPC_UNUSED || msq == IPC_NOID)		return -EIDRM;	if (ipcperms(&msq->msg_perm, msgflg))		return -EACCES;	return msq->msg_perm.seq * MSGMNI +id;} static void freeque (int id){	struct msqid_ds *msq = msgque[id];	struct msg *msgp, *msgh;	msq->msg_perm.seq++;	msg_seq++;	msgbytes -= msq->msg_cbytes;	if (id == max_msqid)		while (max_msqid && (msgque[--max_msqid] == IPC_UNUSED));	msgque[id] = (struct msqid_ds *) IPC_UNUSED;	used_queues--;	while (msq->rwait || msq->wwait) {		if (msq->rwait)			wake_up (&msq->rwait); 		if (msq->wwait)			wake_up (&msq->wwait);		schedule(); 	}	for (msgp = msq->msg_first; msgp; msgp = msgh ) {		msgh = msgp->msg_next;		msghdrs--;		kfree_s (msgp, sizeof(*msgp) + msgp->msg_ts);	}	kfree_s (msq, sizeof (*msq));}int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf){	int id, err;	struct msqid_ds *msq, tbuf;	struct ipc_perm *ipcp;		if (msqid < 0 || cmd < 0)		return -EINVAL;	switch (cmd) {	case IPC_INFO: 	case MSG_INFO: 		if (!buf)			return -EFAULT;	{ 		struct msginfo msginfo;		msginfo.msgmni = MSGMNI;		msginfo.msgmax = MSGMAX;		msginfo.msgmnb = MSGMNB;		msginfo.msgmap = MSGMAP;		msginfo.msgpool = MSGPOOL;		msginfo.msgtql = MSGTQL;		msginfo.msgssz = MSGSSZ;		msginfo.msgseg = MSGSEG;		if (cmd == MSG_INFO) {			msginfo.msgpool = used_queues;			msginfo.msgmap = msghdrs;			msginfo.msgtql = msgbytes;		}		err = verify_area (VERIFY_WRITE, buf, sizeof (struct msginfo));		if (err)			return err;		memcpy_tofs (buf, &msginfo, sizeof(struct msginfo));		return max_msqid;	}	case MSG_STAT:		if (!buf)			return -EFAULT;		err = verify_area (VERIFY_WRITE, buf, sizeof (*msq));		if (err)			return err;		if (msqid > max_msqid)			return -EINVAL;		msq = msgque[msqid];		if (msq == IPC_UNUSED || msq == IPC_NOID)			return -EINVAL;		if (ipcperms (&msq->msg_perm, S_IRUGO))			return -EACCES;		id = msqid + msq->msg_perm.seq * MSGMNI; 		memcpy_tofs (buf, msq, sizeof(*msq));		return id;	case IPC_SET:		if (!buf)			return -EFAULT;		memcpy_fromfs (&tbuf, buf, sizeof (*buf));		break;	case IPC_STAT:		if (!buf)			return -EFAULT;		err = verify_area (VERIFY_WRITE, buf, sizeof(*msq));		if (err)			return err;		break;	}	id = msqid % MSGMNI;	msq = msgque [id];	if (msq == IPC_UNUSED || msq == IPC_NOID)		return -EINVAL;	ipcp = &msq->msg_perm;	if (ipcp->seq != msqid / MSGMNI)		return -EIDRM;	switch (cmd) {	case IPC_STAT:		if (ipcperms (ipcp, S_IRUGO))			return -EACCES;		memcpy_tofs (buf, msq, sizeof (*msq));		return 0;		break;	case IPC_RMID: case IPC_SET:		if (!suser() && current->euid != ipcp->cuid && 		    current->euid != ipcp->uid)			return -EPERM;		if (cmd == IPC_RMID) {			freeque (id); 			return 0;		}		if (tbuf.msg_qbytes > MSGMNB && !suser())			return -EPERM;		msq->msg_qbytes = tbuf.msg_qbytes;		ipcp->uid = tbuf.msg_perm.uid;		ipcp->gid =  tbuf.msg_perm.gid;		ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | 			(S_IRWXUGO & tbuf.msg_perm.mode);		msq->msg_ctime = CURRENT_TIME;		break;	default:		return -EINVAL;		break;	}	return 0;}

⌨️ 快捷键说明

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