PHP和C语言共享内存通信以及信号量互斥
程序分PHP部分和C语言部分。PHP部分提供一个run_php_cmd函数入口参数为命令直接返回C语言处理结果。C语言部分提供一个run_php_cmd入口参数为一个函数,当收到PHP命令时调用该函数。
动作流程为:PHP往共享内存里写数据->释放cmd信号量->C语言从共享内存里读数据->C语言向共享内存里写返回结果->C语言释放ret信号量->PHP等到ret信号量得到返回结果
C语言信号量操作
pv.h:
int sem_creat(key_t key);//生成信号量
void del_sem(int semid);//删除信号量
inline int v(int semid);//v v操作
inline int p(int semid);//p p操作
pv.c:
#include <sys/sem.h>
#include <stdio.h>
#include "pv.h"
union semun {int val;
struct semid_ds *buf;
unsigned short *array;
};
//生成信号量
int sem_creat(key_t key)
{union semun sem;
int semid;
sem.val = 0;
semid = semget(key,1,IPC_CREAT|0666);
if (-1 == semid){printf("create semaphore error\n");return 0;
}
semctl(semid,0,SETVAL,sem);
return semid;
}
//删除信号量
void del_sem(int semid)
{union semun sem;
sem.val = 0;
semctl(semid,0,IPC_RMID,NULL);
}
//v v操作
inline int v(int semid)
{struct sembuf sops={0,+1,0};return (semop(semid,&sops,1));
}
//p p操作
inline int p(int semid)
{struct sembuf sops={0,-1,0};return (semop(semid,&sops,1));
}
#include <sys/sem.h>#include <stdio.h>
#include "pv.h"
union semun { int val; struct semid_ds *buf; unsigned short *array;};//生成信号量
int sem_creat(key_t key){union semun sem;
int semid;
sem.val = 0;
semid = semget(key,1,IPC_CREAT|0666);
if (-1 == semid){ printf("create semaphore error\n");return 0;
}
semctl(semid,0,SETVAL,sem);
return semid;
}
//删除信号量
void del_sem(int semid){union semun sem;
sem.val = 0;
semctl(semid,0,IPC_RMID,NULL);
}
//v v操作
inline int v(int semid){ struct sembuf sops={0,+1,0};return (semop(semid,&sops,1));
}
//p p操作
inline int p(int semid){ struct sembuf sops={0,-1,0};return (semop(semid,&sops,1));
}
C语言创建共享内存以及处理PHP命令
php.h:
#ifndef _PHP_IPCKEY
#define _PHP_IPCKEY 0x0127
#endif
extern int run_php_cmd(int (*do_php_cmd)(void *));
php.c:
#include <sys/shm.h> #include <memory.h> #include "pv.h" #include "php.h" void * php; int cmd_sem; int ret_sem; static int php_setup(int ipckey) { int shmid; shmid = shmget(ipckey,1024,IPC_CREAT|0666); if(shmid == -1){ return -1; } php = (char *)shmat(shmid,0,0); if((int)php == -1) { return -1; } cmd_sem = sem_creat(ipckey); ret_sem = sem_creat(ipckey + 1); memset(php,0,1024); return 0; } inline int php_wait_cmd(void) { return p(cmd_sem); } inline int php_wait_ret(void) { return p(ret_sem); } inline int php_send_ret(void) { return v(ret_sem); } int run_php_cmd(int (*do_php_cmd)(void *)){ int i = 0; if(php_setup(_PHP_IPCKEY)){ return -1; } if(do_php_cmd == NULL) return -2; while(i >= 0){ php_wait_cmd(); for(i = 0; i < 1024; i++){ char *c = (char *)php + i; if(*c == ';') { *c = 0; break; } } i = (* do_php_cmd)(php); php_send_ret(); php_wait_ret(); } del_sem(cmd_sem); del_sem(ret_sem); return -i; }PHP发送命令并输出C语言处理结果
<?php
function run_php_cmd($cmd){
$ipckey = 0×0127;
$cmd_sem = sem_get($ipckey);
$ret_sem = sem_get($ipckey+1);
$shm_sem = sem_get($ipckey+2);
$shmid = shmop_open($ipckey, “w”, 0666, 1024);
$cmd .= “\0;”;
if(sem_acquire($shm_sem)){
shmop_write($shmid, $cmd, 0);
@sem_release($cmd_sem);
if(sem_acquire($ret_sem) && sem_acquire($ret_sem)){
$i = 0;
while($i < 1024){
$c = shmop_read($shmid, $i, 1);
if(!strcmp($c,”\0″)) break;
echo($c);
$i = $i+1;
}
}
}
sem_release($shm_sem);
shmop_close ($shmid );
}
?>
恩,不错!来了留个小脚丫,呵呵
呵呵,强悍。。
lz你这个程序行不通阿。。。php根本就不是像c那样设计共享内存区和信号量的,你这样能成功的几率相当小。。。
程序是行得通的,但是压力大了会有问题,把信号量改成socket通信就稳定了
呵呵,首先行得通是行得通,这我肯定你。但确实像你说的那样不稳定,你也说信号量有问题,php里面定义的是一个system v信号量集里面三个信号量,所以即使是key值一样也会有问题。共享内存区也是一样,php用system v做了自己的共享内存区,如果直接用映射地址访问就会出问题。。。
@hatsune, 你知道问题在哪?我仔细调过,感觉是php里的信号量机制的问题。你有办法让这种通信方式变稳定吗?