您的位置:首页 > 编程语言 > PHP开发

PHP和c 信号与共享内存(附简单类)-2

2009-05-08 12:26 309 查看
下表为系统的共享内存的限制值

SHMMAX 共享内存的最大值,一般为 131072 bytes
SHMMIN 共享内存的最小值,一般为 1 byte
SHMMNI 内存共享部分的最大值,一般为 100
SHMSEG 每个行程所能共享的最大内存空间,一般为 6
  sem_get: 取得信号代码。
  sem_acquire: 捕获信号。
  sem_release: 释出信号。
  shm_attach: 打开建立共享内存空间。
  shm_detach: 中止共享内存空间链接。
  shm_remove: 清除内存空间。
  shm_put_var: 加入或更新内存空间中的变量。
  shm_get_var: 取得内存空间中指定的变量。
  shm_remove_var: 删除内存空间中指定的变量。

<?
class Bright_Message
{

var $bright;
var $SHM_KEY;
var $my_pid;

function Bright_Message($SHM_KEY=null)
{
$this->my_pid = getmypid();//Get own pid
if (is_null($SHM_KEY)) $this->SHM_KEY = '123123123';
$this->bright = shm_attach($this->SHM_KEY, 1024, 0666);
$this->one_instance();
}

function get_msg($id,$remove=true)
{
if(@$msg=shm_get_var($this->bright,$id))
{
if ($remove) @shm_remove_var($this->bright,$id);
return $msg;
} else return false;
}

function snd_msg($id,$msg)
{
@shm_put_var($this->bright,$id,$msg);
return true;
}

function one_instance()
{
$SHM_PID = $this->get_msg(1,false);
if((strpos(exec('ps p'.$SHM_PID),$_SERVER['SCRIPT_FILENAME'])) === false)
$this->snd_msg(1,$this->my_pid); else
{
echo "This program exists on pid: $SHM_PID/r/n/r/n";
exit;
}
}

}
?>

send.php:
<?
include "bridge_message.class.php";
$shm = new Bright_Message();
$shm->snd_msg(2,'this is my simple message');
?>

receive.php:
<?
include "bridge_message.class.php";
$shm = new Bright_Message();
$msg = get_msg(2);
echo print_r($msg,1);
?>

下面c语言的处理:
根据《linux网络编程》p117的例子改编的,因为书上的例子有一些错误,这里进行了改正,并增加了利用信号中断程序,回收资源的功能。

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
/***********************
该文可以任意转载,修改,但需保留出处
修改者:rainfish
出处:http://blog.csdn.net/bat603/
版权归《linux网络编程》所有
*****************/
#define SHMKEY1 (key_t)0x10
#define SHMKEY2 (key_t)0x15

#define SEMKEY (key_t)0x20

#define SIZ 5*BUFSIZ

#define IFLAGS (IPC_CREAT|IPC_EXCL)
#define ERR ((struct databuf*)-1)

struct sembuf p1 = {0, -1, 0};
struct sembuf v1 = {0, 1, 0};
struct sembuf p2 = {1, -1, 0};
struct sembuf v2 = {1, 1, 0};
static int shmid1, shmid2, semid;

struct databuf
{
int d_nread;
char d_buf[SIZ];
};

void
fatal(char *mes)
{
perror(mes);
exit (1);
}

void
getshm (struct databuf **p1, struct databuf **p2)
{//创建共享内存
if ((shmid1=shmget(SHMKEY1, sizeof(struct databuf), 0600|IFLAGS)) < 0)
{
fatal ("shmget");
}

if ((shmid2=shmget(SHMKEY2, sizeof(struct databuf), 0600|IFLAGS)) < 0)
{
fatal ("shmget");
}
//映射
if ((*p1=(struct databuf*)(shmat(shmid1, 0, 0))) == ERR)
{
fatal("shmat");
}

if ((*p2=(struct databuf*)(shmat(shmid2, 0, 0))) == ERR)
{
fatal("shmat");
}

}

int
getsem()
{
//int semid;
if ((semid=semget(SEMKEY, 2, 0600|IFLAGS)) < 0)
{
fatal("segmet");
}
//初始化信号量,假定第一个信号灯没有资源
if (semctl(semid, 0, SETVAL, 0) < 0)
{
fatal ("semctl");
}
//第二个有信息,如果两个信号都没有资源,将会出现死锁
//书上该处有问题
if (semctl(semid, 1, SETVAL, 1) < 0)
{
fatal ("semctl");
}

return (semid);
}

void
myremove()
{
if (shmctl(shmid1, IPC_RMID, NULL) < 0)
{
fatal("shmctl");
}
if (shmctl(shmid2, IPC_RMID, NULL) < 0)
{
fatal("shmctl");
}
if (semctl(semid, 0, IPC_RMID, NULL) < 0)
fatal("semctl");
exit(0);
}

void
reader(int semid, struct databuf *buf1, struct databuf *buf2)
{
for(;;)
{
//从键盘读入数据,放在buf1->d_buf,
//read第一个参数是文件描述符,其中0表示从终端输入:如键盘
buf1->d_nread = read(0, buf1->d_buf, SIZ);
//v操作,释放第一个信号灯资源
semop(semid, &v1, 1);
//p操作,申请第二个信号灯资源,若没有资源,则阻塞进程直到有资源.
semop(semid, &p2, 1);

buf2->d_nread = read(0, buf2->d_buf, SIZ);

semop(semid, &v2, 1);
semop(semid, &p1, 1);

}

}

void
writer(int semid, struct databuf *buf1, struct databuf *buf2)
{
for(;;)
{
//p操作,等待第一个信号的资源
semop(semid, &p1, 1);
//1代表输出到屏幕
write(1, buf1->d_buf, buf1->d_nread);

semop(semid, &v1, 1);
semop(semid, &p2, 1);

write(1, buf2->d_buf, buf2->d_nread);

semop(semid, &v2, 1);
}
}

int
main()
{
int semid, pid;

struct databuf *buf1, *buf2;

semid = getsem();
getshm (&buf1, &buf2);

switch(pid=fork())
{
case -1:
fatal("fork");
break;
case 0:
writer(semid, buf1, buf2);
break;
default:
//在主进程中把中断程序的ctrl+c和myremove函数建立联系,来回收系统资源:共享内存区,信号量.
signal (SIGINT, myremove);
reader(semid, buf1, buf2);
break;
}
exit(0);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: