您的位置:首页 > 运维架构 > Linux

用swig给Python增加Linux下的IPC模块

2004-10-25 13:46 375 查看
我负责的一套系统,运行与linux中,模块之间使用linux消息队列通讯的。现在有个地方需要单独一个通讯模块的功能。要我写个通讯接口。本来想用c++来写,后来考虑一下觉得用python跟快捷,跟便于维护。
就上网找python的linux下消息队列相关模块。找到Walter de Jong写的模块:
http://www.xs4all.nl/~walterj/python-ipc/

实际测试一下,发现使用起来不是很方便。就觉得之间改改它。
通过这个模块我才知道swig是如何使用的,就到swig的官方网站去下载了一个最新版安装。

用swig给Python增加Linux下的IPC模块

1、下载安装最新版本的SWIG-1.3.22
tar zxvf swig-1.3.22.tar.gz
cd SWIG-1.3.22/
./configure
make
make install
此时swig被安装到了/usr/local/bin目录下。需要把老版本的swig给改名了。
mv /usr/bin/swig /usr/bin/swig1.1

2、下面是修改后的ipc包的文件,主要只有3个文件ipc.h,ipc.i,Makefile
ipc.h:
/*
ipc.h WJ103

This file is a rip-off of the standard includes:
/usr/include/sys/types.h
/usr/include/sys/ipc.h
/usr/include/sys/shm.h
/usr/include/bits/shm.h
etc.

If things do not work, check for differences between those files
and this one. I'm sorry, I could not get it done in any other way...
*/

#include <sys/types.h>

#define IPC_CREAT 01000 /* Create key if key does not exist. */
#define IPC_EXCL 02000 /* Fail if key exists. */
#define IPC_NOWAIT 04000 /* Return error on wait. */

/* Control commands for `msgctl', `semctl', and `shmctl'. */
#define IPC_RMID 0 /* Remove identifier. */
#define IPC_SET 1 /* Set `ipc_perm' options. */
#define IPC_STAT 2 /* Get `ipc_perm' options. */
#define IPC_INFO 3 /* See ipcs. */

/* Special key values. */
#define IPC_PRIVATE ((key_t)0) /* Private key. */

/* Permission flag for shmget. */
#define SHM_R 0400 /* or S_IRUGO from <linux/stat.h> */
#define SHM_W 0200 /* or S_IWUGO from <linux/stat.h> */

/* Flags for `shmat'. */
#define SHM_RDONLY 010000 /* attach read-only else read-write */
#define SHM_RND 020000 /* round attach address to SHMLBA */
#define SHM_REMAP 040000 /* take-over region on attach */

/* Commands for `shmctl'. */
#define SHM_LOCK 11 /* lock segment (root only) */
#define SHM_UNLOCK 12 /* unlock segment (root only) */

/* ipcs ctl commands */
#define SHM_STAT 13
#define SHM_INFO 14

/* shm_mode upper byte flags */
#define SHM_DEST 01000 /* segment will be destroyed on last detach */
#define SHM_LOCKED 02000 /* segment will not be swapped */

/* Permission struct */
struct ipc_perm {
key_t __key; /* Key. */
unsigned short int uid; /* Owner's user ID. */
unsigned short int gid; /* Owner's group ID. */
unsigned short int cuid; /* Creator's user ID. */
unsigned short int cgid; /* Creator's group ID. */
unsigned short int mode; /* Read/write permission. */
unsigned short int __seq; /* Sequence number. */
};

/* Data structure describing a set of semaphores. */
struct shmid_ds
{
struct ipc_perm shm_perm; /* operation permission struct */
int shm_segsz; /* size of segment in bytes */
time_t shm_atime; /* time of last shmat() */
time_t shm_dtime; /* time of last shmdt() */
time_t shm_ctime; /* time of last change by shmctl() */
pid_t shm_cpid; /* pid of creator */
pid_t shm_lpid; /* pid of last shmop */
unsigned short int shm_nattch; /* number of current attaches */
unsigned short int __shm_npages; /* size of segment (pages) */
unsigned long int *__shm_pages; /* array of ptrs to frames -> SHMMAX */
void *__attaches; /* descriptors for attaches */
};

struct shminfo {
int shmmax;
int shmmin;
int shmmni;
int shmseg;
int shmall;
};

struct shm_info {
int used_ids;
unsigned long int shm_tot; /* total allocated shm */
unsigned long int shm_rss; /* total resident shm */
unsigned long int shm_swp; /* total swapped shm */
unsigned long int swap_attempts;
unsigned long int swap_successes;
};

/* Flags for `semop'. */
#define SEM_UNDO 0x1000 /* undo the operation on exit */

/* Commands for `semctl'. */
#define GETPID 11 /* get sempid */
#define GETVAL 12 /* get semval */
#define GETALL 13 /* get all semval's */
#define GETNCNT 14 /* get semncnt */
#define GETZCNT 15 /* get semzcnt */
#define SETVAL 16 /* set semval */
#define SETALL 17 /* set all semval's */

/* Data structure describing a set of semaphores. */
struct semid_ds
{
struct ipc_perm sem_perm; /* operation permission struct */
time_t sem_otime; /* last semop() time */
time_t sem_ctime; /* last time changed by semctl() */
struct sem *__sembase; /* ptr to first semaphore in array */
struct sem_queue *__sem_pending; /* pending operations */
struct sem_queue *__sem_pending_last; /* last pending operation */
struct sem_undo *__undo; /* ondo requests on this array */
unsigned short int sem_nsems; /* number of semaphores in set */
};

/*
According to X/Open you have to define the union semun yourself.
What the crap is that all about anyway??? It's probably just because
of its name. Well, here it is. I define the semun myself. Ha!

--Walter
*/
union semun {
int val; /* value for SETVAL */
struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
unsigned short int *array; /* array for GETALL & SETALL */
struct seminfo *__buf; /* buffer for IPC_INFO */
};

/* ipcs ctl cmds */
#define SEM_STAT 18
#define SEM_INFO 19

struct seminfo
{
int semmap;
int semmni;
int semmns;
int semmnu;
int semmsl;
int semopm;
int semume;
int semusz;
int semvmx;
int semaem;
};

/*
Note: use the helper function mkmsgbuf() to create a message buffer
This structure is merely used for typecasting a larger object
*/
struct msgbuf
{
long int mtype; /* type of received/sent message */
char mtext[2048]; /* text of the message */
};

/* Define options for message queue functions. */
#define MSG_NOERROR 010000 /* no error if message is too big */
#define MSG_EXCEPT 020000 /* recv any msg except of specified type */

/* Structure of record for one message inside the kernel.
The type `struct msg' is opaque. */
struct msqid_ds
{
struct ipc_perm msg_perm; /* structure describing operation permission */
struct msg *__msg_first; /* pointer to first message on queue */
struct msg *__msg_last; /* pointer to last message on queue */
time_t msg_stime; /* time of last msgsnd command */
time_t msg_rtime; /* time of last msgrcv command */
time_t msg_ctime; /* time of last change */
void *__wwait; /* ??? */
void *__rwait; /* ??? */
unsigned short int __msg_cbytes;/* current number of bytes on queue */
unsigned short int msg_qnum; /* number of messages currently on queue */
unsigned short int msg_qbytes;/* max number of bytes allowed on queue */
pid_t msg_lspid; /* pid of last msgsnd() */
pid_t msg_lrpid; /* pid of last msgrcv() */
};

/*
#define msg_cbytes __msg_cbytes
*/

/* ipcs ctl commands */
#define MSG_STAT 11
#define MSG_INFO 12

/* buffer for msgctl calls IPC_INFO, MSG_INFO */
struct msginfo {
int msgpool;
int msgmap;
int msgmax;
int msgmnb;
int msgmni;
int msgssz;
int msgtql;
unsigned short int msgseg;
};

/* EOB */

swig的接口定义文件:ipc.i
//
// ipc.i WJ103
//

%module ipc
%{
#include "ipc.h"
%}

// Produce constants and helper functions for structures and unions
%include "ipc.h"

int ftok(char *, char);

int shmget(int, int, int);
void *shmat(int, void *, int);
int shmdt(void *);
int shmctl(int, int, struct shmid_ds *);

int semget(int, int, int);
int semctl(int, int, int, union semun);
int semop(int, struct sembuf *, unsigned int);

int msgget(int, int);
int msgctl(int, int, struct msqid_ds *);
int msgsnd(int, struct msgbuf *, int, int);
int msgrcv(int, struct msgbuf *, int, long, int);

%inline
%{
%}

// EOB

编译定义文件Makefile
#
# Makefile
#
# python ipc module by Walter de Jong <walter@heiho.net>
#

CC=gcc
COPT=-g #-O2 -Winline
CFLAGS=$(COPT) -Wall
CFLAGSWRAP = $(COPT) -fpic
CFLAGSSO = $(COPT) -shared

SWIG=swig
PYTHON_INCLUDE=/usr/include/python2.2

OBJS=ipc_wrap.o

all: _ipc.so

_ipc.so: $(OBJS)
$(CC) $(CFLAGSSO) $(OBJS) -o _ipc.so

ipc_wrap.o: ipc_wrap.c
$(CC) $(CFLAGSWRAP) -c ipc_wrap.c -Dbool=char -I. -I$(PYTHON_INCLUDE)

ipc_wrap.c: ipc.i
$(SWIG) -python ipc.i

.c.o:
$(CC) $(CFLAGS) -c $<

clean:
rm -f $(OBJS) _ipc.so ipc.py ipc.pyc ipc_wrap.c ipc_wrap.doc

# EOB

编译:

执行make
程序编译后生成了:
ipc.py,ipc.pyc模块文件,以及模块支持库_ipc.so

3、用法介绍:

由于我只使用消息队列相关函数,所以没有对其它函数进行测试!


>>> import ipc
>>> dir(ipc)
['GETALL', 'GETNCNT', 'GETPID', 'GETVAL', 'GETZCNT', 'IPC_CREAT', 'IPC_EXCL', 'IPC_INFO', 'IPC_NOWAIT', 'IPC_RMID', 'IPC_SET', 'IPC_STAT', 'MSG_EXCEPT', 'MSG_INFO', 'MSG_NOERROR', 'MSG_STAT', 'SEM_INFO', 'SEM_STAT', 'SEM_UNDO', 'SETALL', 'SETVAL', 'SHM_DEST', 'SHM_INFO', 'SHM_LOCK', 'SHM_LOCKED', 'SHM_R', 'SHM_RDONLY', 'SHM_REMAP', 'SHM_RND', 'SHM_STAT', 'SHM_UNLOCK', 'SHM_W', '__builtins__', '__doc__', '__file__', '__name__', '_ipc', '_newclass', '_object', '_swig_getattr', '_swig_setattr', 'ftok', 'ipc_perm', 'ipc_permPtr', 'msgbuf', 'msgbufPtr', 'msgctl', 'msgget', 'msginfo', 'msginfoPtr', 'msgrcv', 'msgsnd', 'msqid_ds', 'msqid_dsPtr', 'semctl', 'semget', 'semid_ds', 'semid_dsPtr', 'seminfo', 'seminfoPtr', 'semop', 'semun', 'semunPtr', 'shm_info', 'shm_infoPtr', 'shmat', 'shmctl', 'shmdt', 'shmget', 'shmid_ds', 'shmid_dsPtr', 'shminfo', 'shminfoPtr']

建立消息队列:
>>> msgid = ipc.msgget(0x10012,0666|ipc.IPC_CREAT)
>>> msgid
65538
此时用ipcs 查看,可以看到消息队列已经创建成功
发送消息:
>>> mbuf = ipc.msgbuf()
>>> mbuf
<C msgbuf instance at _f0931908_p_msgbuf>
>>> mbuf.mtype = 1
>>> mbuf.mtext = 'abc'
>>> ipc.msgsnd(msgid,mbuf,3,0)
0
此时用ipcs 查看,消息队列中有一个消息
接收消息队列
>>> rbuf = ipc.msgbuf()
>>> ipc.msgrcv(msgid,rbuf,2048,1,0)
3
>>> rbuf.mtype
1
>>> rbuf.mtext
'abc/x00/x00/x00'后面省略...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: