首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

小弟我无聊的时候写了一个自己跟自己说话的程序

2013-01-28 
我无聊的时候写了一个自己跟自己说话的程序我原本的想法是同时打开两个终端,运行同一个程序,然后互相说话

我无聊的时候写了一个自己跟自己说话的程序
我原本的想法是同时打开两个终端,运行同一个程序,然后互相说话
用IPC实现的,编译也通过了
可是P操作总是返回0,不返回-1
代码:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>


union semun {
  int val;
  struct semid_ds *buf;
  unsigned short *array;
  struct seminfo *__buf;
};

int P(int semid)
{
  struct sembuf sops = {0,-1,IPC_NOWAIT};
  int t = semop(semid,&sops,1);
  return t;
}

int V(int semid)
{
  struct sembuf sops = {0,1,SEM_UNDO};
  return (semop(semid,&sops,1));
}

#define length 1024
int main()
{
  int shmkey= ftok("./share",1);
  int semkey= ftok("./shmem",1);
  int shmid,semid;
  int wait = 0;
  char *shmptr;
  //生成共享内存和信号量 
  if((shmid = shmget(shmkey,length,IPC_CREAT))==-1)
    {
      perror("shmget error \n");
      exit(1);
    }
  semid = semget(semkey,1,IPC_CREAT);
  if(semid==-1)
    {
      semid = semget(semkey,1,IPC_EXCL);
      if(semid ==-1)
{
  perror("semget error \n");
  exit(1);
}
    }
   //信号量置1 
  union semun arg;
  arg.val = 1;
  if((int)(shmptr=(char*)(shmat(shmid,NULL,0)))==-1)
    {
      perror("shmat error \n");
      exit(1);
    }

   if(semctl(semid,0,SETVAL,arg)==-1)
    {
      perror("semctl error \n");
      semctl(semid,0,IPC_RMID,arg);
      exit(1);
      }
    //开始聊天 
  while(1)
    {
      while( (P(semid) == -1)||(semctl(semid,0,GETZCNT,arg)>0))//gdb检查是出问题的地方,每次都不会进入这个循环
  {
    printf("waiting for enter...");
        wait = 1;
    sleep(1);
   }
      if( wait==1 )
  {
   printf(":%s\n",shmptr);
   }
      printf("say something:");
      scanf("%s",shmptr);
      while( V(semid) == -1)
  {
   printf("wait transferring \n");
   sleep(3);
   }
    }
  return 0;
}
[解决办法]
(semctl(semid,0,GETZCNT,arg)>0)
看看errno是什么
------解决方案--------------------


程序改了一下,只能保证正确运行,但不怎么优美和健壮,主要应正确使用API


如果上次非法退出进程,在再次运行程序之前,需要清理一下内核对象
program destory



#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

union semun {
int val;
struct semid_ds * buf;
unsigned short * array;
struct seminfo * __buf;
};

int P(int semid) {
struct sembuf sops = { 0, -1, IPC_NOWAIT };
int t = semop(semid, &sops, 1);
return t;
}

int V(int semid) {
struct sembuf sops = { 0, 1, SEM_UNDO };
return (semop(semid, &sops, 1));
}

#define length 1024
int main(int argc, char *argv[]) {
// 生成key,必须在当前目录下存在share和shmem文件,否则错误,返回-1
int shmkey = ftok("share", 1);
int semkey = ftok("shmem", 1);
printf("%d\n", shmkey);
printf("%d\n", semkey);
// 根据key新创建共享内存
int shmid = shmget(shmkey, length, IPC_CREAT 
[解决办法]
 IPC_EXCL);
if (shmid == -1) {
// 如果新创建失败,则以访问的形式操作共享内存
shmid = shmget(shmkey, 0, 0);
if (shmid == -1) {
perror("shmget error \n");
exit(1);
}
}

// 根据key新创建信号量
int semid = semget(semkey, 1, IPC_CREAT 
[解决办法]
 IPC_EXCL);
union semun arg;
arg.val = 1;
if (semid == -1) {
printf("client get sem\n");
semid = semget(semkey, 0, 0);
if (semid == -1) {
perror("semget error \n");
exit(1);
}
} else {
// 新的信号量创建成功,设置资源数为1
if (semctl(semid, 0, SETVAL, arg) == -1) {
perror("semctl error \n");
semctl(semid, 0, IPC_RMID, arg);
exit(1);
}
}
int ret;
// 此处用于因上一次非法退出进程而未销毁内核对象
// system v的内核对象是持久化的,即使所有访问进程终止了,
// 该内核对象还存在,不会自动销毁
if (argc > 1 && !strcmp(argv[1], "destory")) {
ret = semctl(semid, 0, IPC_RMID);
if (ret != 0) {
perror("semctl destory sem error");
}
ret = shmctl(shmid, 0, IPC_RMID);
if (ret != 0) {
perror("shmctl destory shm error");
}
return 0;
}

int wait = 0;
char * shmptr;

if ((int) (shmptr = (char *) (shmat(shmid, NULL, 0))) == -1) {
perror("shmat error \n");
exit(1);
}

while (1) {
while ((P(semid) == -1) 
[解决办法]
 (semctl(semid, 0, GETZCNT, arg) > 0)) {
printf("waiting for enter...\n");
wait = 1;
sleep(1);
}


if (wait == 1) {
printf(":%s\n", shmptr);
}
printf("say something:\n");
scanf("%s", shmptr);
while (V(semid) == -1) {
printf("wait transferring \n");
sleep(3);
}

// 发完消息,等待1s再发送消息
sleep(1);

}

// 正常销毁内核对象
ret = semctl(semid, 0, IPC_RMID);
if (ret != 0) {
perror("semctl destory sem error");
}
ret = shmctl(shmid, 0, IPC_RMID);
if (ret != 0) {
perror("shmctl destory shm error");
}
return 0;
}

热点排行