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

来源:互联网 发布:2017淘宝开店卖什么好 编辑:程序博客网 时间:2024/05/16 15:37

我负责的一套系统,运行与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'后面省略...



  

原创粉丝点击