进程间通讯

结合个人开发经验,讲诉多进程编程,并结合oracle进程管理进行探讨.整理时间:2009-11-01 至2009-11-30

-------这段时间一直在研究足球彩票,以至于没时间更新blog,这是以前总结部分内容,暂时放上来.......

[@more@]

IPC(InterProcess Communication)主要包括:管道、FIFO、信息队列、信号量及共享内存等。不包括Socket。
1、管道
优点:半双工管道是最常用的,如shell管道。
缺点:a、以前以半双工的方式存在,现在个别系统提供全双工方式;b、只能父子进程之间通信。
应用简单说明:
(1)创建管道pipe(filedes[2]),其中filedes[0]读read(filedes[0],buf,sizeof(buf));filedes[1]写 write(filedes[1],s,sizeof(s))
(2)管道方向:父进程->子进程 父进程关闭读filedes[0];子进程关闭写filedes[1];反之成立。
#include
#include

int main( void )
{
int filedes[2];
char buf[80];
pid_t pid;
char buf2[80];
pipe( filedes );

if ( (pid=fork()) > 0 )
{
printf( "This is in the father process,here write a string to the pipe.n" );
char s[] = "Hello world , this is write by pipe.n";
close( filedes[0] );
write( filedes[1], s, sizeof(s) );
}
else
{
printf( "This is in the child process,here read a string from the pipe.n" );
close( filedes[1] );
read( filedes[0], buf, sizeof(buf) );
printf( "%sn", buf );
}
waitpid( pid, NULL, 0 );
return 0;
}

2、FIFO(命名管道)
优点:不相关进程进行交换数据,区别于管道局限于父子进程。一般文件I/O函数都可用于FIFO
缺点:
应用简单说明:
(1)创建FIFO mkfifo(const char *pathname,mode_t mode);打开管道open(FIFO,O_RDONLY|O_NONBLOCK,0); 读read,写write同文件操作。
#include
#include
#include
#include
#include
#include
#include

/*FIFO管道路径*/
#define FIFO_SERVER "/tmp/myfifo"

int main(int argc,char** argv)
{
int fd = 0;
char w_buf[100];
int nwrite;
/*打开FIFO管道*/
fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);
if(fd==-1)
if(errno==ENXIO)
printf("open error; no reading processn");
/*判断有没有参数输入*/
if(argc==1)
printf("Please send somethingn");
/*复制参数输入*/
strcpy(w_buf,argv[1]);
/*写到FIFO去*/
if((nwrite=write(fd,w_buf,100))==-1)
{
if(errno==EAGAIN)
printf("The FIFO has not been read yet.Please try latern");
}
else
/*输出写入的内容*/
{
printf("write %s to the FIFOn",w_buf);
}
return 0;
}

[etl@localhost FIFO]$ ls
client.cpp
[etl@localhost FIFO]$ cat >server.cpp
#include
#include
#include
#include
#include
#include
#include

/*定义FIFO路径*/
#define FIFO "/tmp/myfifo"

main(int argc,char** argv)
{
char buf_r[100];
int fd;
int nread;
/*创建FIFO管道*/
if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
printf("cannot create fifoservern");
printf("Preparing for reading bytes...n");

memset(buf_r,0,sizeof(buf_r));
/*打开FIFO管道,不阻塞方式*/
fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
if(fd==-1)
{
perror("open");
exit(1);
}
while(1)
{
memset(buf_r,0,sizeof(buf_r));
/*读管道,因为定义了非阻塞方式,故在此不会阻塞进程*/
if((nread=read(fd,buf_r,100))==-1){
if(errno==EAGAIN)
printf("no data yetn");
}
printf("read %s from FIFOn",buf_r);
sleep(1);
}
pause();
unlink(FIFO);
}

3、消息队列

应用简单说明:一般应用为主进程每发起一个任务,生成一个子进程处理任务并反回处理结果。
#include
#include
#include
#include
#include
#include
static struct msgbuf1
{
long mtype;
char mtext[100];
} sndbuf, rcvbuf, *msgp ;

extern int errno;

int main(int argc, char **argv)
{
int rtrn, msqid ;
char name[10];
double balance;

if (argc!=2)
{
fprintf(stderr,"msgreq [01-99]n"); exit(-1);
}
if ((msqid = msgget(0x888, IPC_CREAT|0660)) == -1 )
{
fprintf(stderr, "msgget 888 failed !n");
//exit(-1);
}
msgp=&sndbuf;

sprintf(sndbuf.mtext,"%2.2s",argv[1]);
printf("输入4位帐号:");
scanf("%s",&sndbuf.mtext[2]);

sndbuf.mtext[6]=0;
msgp->mtype=666;
rtrn=msgsnd(msqid,msgp, strlen(sndbuf.mtext), 0);
if (rtrn==-1)
{
perror("msgsnd"); exit(-1);
}
msgp=&rcvbuf;

fprintf(stderr,"等待后台数据处理进程的回答....");

rtrn=msgrcv(msqid,msgp, 100, atoi(argv[1]), 0);
if(rtrn==-1)
{
perror("msgrcv"); exit(-1);
}

sscanf(rcvbuf.mtext,"%[^|]|%lf",name,&balance);
printf("n姓名=%sn",name);
printf("余额=%lfn",balance);
}

/*服务方程序msgcenter.c*/
#include
#include
#include
#include
#include
#include

static struct msgbuf1
{
long mtype;
char mtext[100];
} sndbuf, rcvbuf , *msgp;

extern int errno;

int main()
{
int rtrn, msqid ;
char strbuf[100];

if ( (msqid = msgget(0x888, IPC_CREAT|0600)) == -1 )
{
fprintf(stderr, "msgget 888 failed !n"); exit(-1);
}

while(1)
{
msgp=&rcvbuf;
fprintf(stderr,"等待前台进程的请求....");

rtrn=msgrcv(msqid, msgp, 100, 666 ,MSG_NOERROR);
if(rtrn==-1)
{
perror("msgrcv");exit(-1);
}
msgp=&sndbuf;
sprintf(strbuf,"%2.2s",rcvbuf.mtext);
msgp->mtype=atoi(strbuf);
printf("n输入帐号=%4.4s的帐户姓名:",&rcvbuf.mtext[2]);

scanf("%s",sndbuf.mtext);
strcat(sndbuf.mtext,"|");
printf("输入该帐户余额:");
scanf("%s",strbuf);
strcat(sndbuf.mtext,strbuf);
rtrn=msgsnd(msqid,msgp, strlen(sndbuf.mtext), 0);
if (rtrn==-1)
{
perror("msgsnd");
exit(-1);
}
}
}

4、信号量
5、共享内存


#include
#include
#include

struct lcd_info {
int width; // 屏宽
int height; // 屏高
int depth; // 每点像素数
int line_bytes; // 每行字节数
int data_offset;// 数据区开始偏移值
};

int shmId;

int main(void)
{
int data_size;
void *data;
struct lcd_info lcd;
struct shmid_ds shm;

key_t key = ftok("/sbin/init", 'g');
// 根据init文件的ino节点号,dev设备号,和id组合出一个key序列串,作为唯一key标识[luthr.gliethttp]
// ftok库实现为
// key_t ftok(const char* path, int id)
// {
// struct stat st;
// if ( lstat(path, &st) < 0 )
// return -1;
// return (key_t)( (st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | ((id & 255) << 24) );
// }

lcd.width = 800;
lcd.height = 600;
lcd.depth = 16;
lcd.line_bytes = lcd.width * ((lcd.depth+7) >> 3);
lcd.data_offset = 512;
data_size = lcd.line_bytes*lcd.height + lcd.data_offset; // 0-511字节存放控制信息[luther.gliethttp]
// 跳过前512字节的控制信息空间[luther.gliethttp]

shmId = shmget( key, data_size, IPC_CREAT|0666); // 创建一个data_size大小的共享内存,该共享内存
// 对应的唯一索引值为key,调用shmget(key, 0, 0);可以获得该共享内存[luther.gliethttp]
if ( shmId != -1 )
data = (unsigned char *)shmat( shmId, 0, 0 );
else {
shmctl( shmId, IPC_RMID, &shm ); // 删除已经存在的key相同的共享内存[luther.gliethttp].
shmId = shmget( key, data_size, IPC_CREAT|0666);
data = (unsigned char *)shmat( shmId, 0, 0 );
}

if ((int)data == -1) {
printf("Error : shmgetn");
return -1;
}

*((struct lcd_info*)data) = lcd;

for (;;) {
sleep(1);
}

shmctl( shmId, IPC_RMID, &shm ); // 删除共享内存,当然这里是不会执行到这了,应该在signal回调函数中执行,不过再次启动的时候,会自动删除[luther.gliethttp].
return 0;
}


#include
#include
#include

struct lcd_info {
int width; // 屏宽
int height; // 屏高
int depth; // 每点像素数
int line_bytes; // 每行字节数
int data_offset;// 数据区开始偏移值
};

int shmId;

int main(void)
{
struct lcd_info *lcd;

key_t key = ftok("/sbin/init", 'g');
// 根据init文件的ino节点号,dev设备号,和id组合出一个key序列串,作为唯一key标识[luthr.gliethttp]
// ftok库实现为
// key_t ftok(const char* path, int id)
// {
// struct stat st;
// if ( lstat(path, &st) < 0 )
// return -1;
// return (key_t)( (st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | ((id & 255) << 24) );
// }

shmId = shmget(key, 0, 0);
if (shmId != -1)
lcd = shmat(shmId, 0, 0);
else {
printf("[luther.gliethttp] shmId=-1n");
return -1;
}

printf("=====[luther.gliethttp.lcd.info]=====n"
"widthtt= %dn"
"heighttt= %dn"
"depthtt= %dn"
"line_bytest= %dn"
"data_offsett= %dn",
lcd->width,
lcd->height,
lcd->depth,
lcd->line_bytes,
(unsigned int)lcd->data_offset);
return 0;
}

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22630256/viewspace-1027636/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/22630256/viewspace-1027636/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值