Messages in this thread Patch in this message | | | Date | Mon, 03 Dec 2001 18:21:20 +0100 | From | Jean-Christian de Rivaz <> | Subject | [RFC][PATCH]/dev/ipc/* to poll a message |
| |
Hi all,
This patch show a possibiliy to add a device per IPC message queue in order to use the poll() or select() call. The goal is to have a easy way in an application to wait on a IPC message in it main loop. This is just to try and to have some code to talk about. Follow the patch and samples applications.
Future work can be: - debug :-) - Config.in to controle CONFIG_IPC_DEV. - removing device on ipcrm. - ioctl to control type and mode of message to wait. - read methode to replace msgrcv() ? - write methode to replace msgsnd() ? - speciale device (like /dev/ppp) to replace msgget() ? - ...
Any comment ?
=== kernel patch =====================================================
--- ipc/msg.c 2001/10/03 09:03:38 1.1.1.13 +++ ipc/msg.c 2001/12/03 15:57:37 @@ -15,6 +15,8 @@ * (c) 1999 Manfred Spraul <manfreds@colorfullife.com> */ +#define CONFIG_IPC_DEV + #include <linux/config.h> #include <linux/slab.h> #include <linux/msg.h> @@ -24,6 +26,10 @@ #include <linux/list.h> #include <asm/uaccess.h> #include "util.h" +#ifdef CONFIG_IPC_DEV +#include <linux/poll.h> +#include <linux/devfs_fs_kernel.h> +#endif /* sysctl: */ int msg_ctlmax = MSGMAX; @@ -79,6 +85,9 @@ struct list_head q_messages; struct list_head q_receivers; struct list_head q_senders; +#ifdef CONFIG_IPC_DEV + wait_queue_head_t ipc_dev_wait; /* For the poll methode */ +#endif }; #define SEARCH_ANY 1 @@ -112,11 +121,51 @@ #ifdef CONFIG_PROC_FS create_proc_read_entry("sysvipc/msg", 0, 0, sysvipc_msg_read_proc, NULL); #endif +#ifdef CONFIG_IPC_DEV + devfs_mk_dir(NULL, "ipc", NULL); +#endif +} + +#ifdef CONFIG_IPC_DEV +static unsigned int ipc_dev_poll(struct file *file, poll_table *wait) +{ + int msqid=(int)file->private_data; + struct msg_queue *msq; + unsigned int ret = 0; + + msq = msg_lock(msqid); + if(msq==NULL) + return -EINVAL; + ret = -EIDRM; + if (msg_checkid(msq,msqid)) + goto out_unlock; + ret = -EACCES; + if (ipcperms (&msq->q_perm, S_IRUGO)) + goto out_unlock; + + poll_wait(file, &msq->ipc_dev_wait, wait); + + ret = 0; + if(msq->q_qnum) + ret = POLLIN | POLLRDNORM; + +out_unlock: + msg_unlock(msqid); + return ret; } +static struct file_operations ipc_dev_fops = { + poll: ipc_dev_poll, +}; +#endif + static int newque (key_t key, int msgflg) { int id; +#ifdef CONFIG_IPC_DEV + int msgid; + char name[32]; +#endif struct msg_queue *msq; msq = (struct msg_queue *) kmalloc (sizeof (*msq), GFP_KERNEL); @@ -138,9 +187,21 @@ INIT_LIST_HEAD(&msq->q_messages); INIT_LIST_HEAD(&msq->q_receivers); INIT_LIST_HEAD(&msq->q_senders); +#ifdef CONFIG_IPC_DEV + init_waitqueue_head(&msq->ipc_dev_wait); +#endif msg_unlock(id); +#ifdef CONFIG_IPC_DEV + msgid = msg_buildid(id,msq->q_perm.seq); + sprintf(name, "ipc/%d", msgid); + devfs_register(NULL, name, + DEVFS_FL_DEFAULT, 0, 0, S_IFREG | S_IRUSR, + &ipc_dev_fops, (void*)msgid); + return msgid; +#else return msg_buildid(id,msq->q_perm.seq); +#endif } static void free_msg(struct msg_msg* msg) @@ -686,6 +747,9 @@ msq->q_lspid = current->pid; msq->q_stime = CURRENT_TIME; +#ifdef CONFIG_IPC_DEV + wake_up_interruptible_sync(&msq->ipc_dev_wait); +#endif if(!pipelined_send(msq,msg)) { /* noone is waiting for this message, enqueue it */ list_add_tail(&msg->m_list,&msq->q_messages); === send.c =========================================================== #include <assert.h> #include <stdio.h> #include <string.h> #include <sys/msg.h>
#define KEY 1235 #define MSGSZ 200
typedef struct msgbuftoto { long mtype; char mtext[MSGSZ]; } msgtoto; int main(int argc, char *argv[]) { int ret; int msqid; msgtoto toto; assert((msqid=msgget(KEY, 0664|IPC_CREAT))!=-1); printf("msqid=%d\n", msqid); toto.mtype=1; strncpy(toto.mtext, argv[1], MSGSZ); assert((ret=msgsnd(msqid, (struct msgbuf*)&toto, MSGSZ, 0))!=-1); return 0; } === poll_receive.c ===================================================== #include <assert.h> #include <fcntl.h> #include <stdio.h> #include <sys/msg.h> #include <sys/poll.h> #include <sys/types.h> #include <sys/stat.h>
#define KEY 1235 #define MSGSZ 200
typedef struct msgbuftoto { long mtype; char mtext[MSGSZ]; } msgtoto; int main(int argc, char *argv[]) { int ret; int msqid; char name[32]; struct pollfd pfd; msgtoto toto; assert((msqid=msgget(KEY, 0664|IPC_CREAT))!=-1); sprintf(name, "/dev/ipc/%d", msqid); assert((pfd.fd=open(name, O_RDONLY))!=-1); pfd.events=POLLIN; printf("poll start...\n"); assert(poll(&pfd, 1, -1)!=-1); printf("poll done!\n"); assert((ret=msgrcv(msqid, (struct msgbuf*)&toto, MSGSZ, 0, 0))!=-1); assert(close(pfd.fd)!=-1); printf("%s\n", toto.mtext); return 0; } =================================================================== -- Jean-Christian de Rivaz mailto:jc@lightning.ch - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |