QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 764|回复: 2

一个简单的共享内存下的ipc应用

[复制链接]
发表于 2003-11-2 15:03:25 | 显示全部楼层 |阅读模式
我做了共享内存下的ipc那个实验,老是出问题,我看不出来。
请各位帮我看看。在linux下试过了,也用gdb看过。我觉得问题可能出在内存共享方面。
      大体是这样的:fork后,父进程读文件,此时我采用sleep让子进程
等待父进程读完才能操作(判断是否为回文)。然后父进程wait,等子进程
判断完并将结果输出完后,exit(0),结束。此前子进程已结束。
      我用gdb看过,读文件内容到内存中操作没问题,内存中结果也对。
但到了子进程工作时,从内存中读出数据时,读出的并非文件内容。而且
子进程中指向共享内存的指针(c_addr)所指内容也不是文件内容。即此
指针不对,但我是用c_addr=shmat(shmid,0,0);不知到底错在哪里。
[code:1]
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>




int func(char str1[],char str2[])//判断是否为回文
{
   char str[128];
   
   int i=0,j=0;
   while(str1[j]!='\0')
   {
      if(str1[j]!=' ')
      {
        str[i]=str1[j];
        i++;
      }
      j++;
   }
   str1[i]='\0';
   i--;
   j=0;
   while(i>=0)
     str2[j++]=str1[i--];
   
   str2[j]='\0';  
   if(strcmp(str,str2)==0)
     return 1;
   else return 0;
}

int main(int argc,char **argv)
{
        int shmid;
        pid_t pid,cid;
        int count=0;
        int leng;
        int i,k;
        char ch='\0';
        char filename[20];
        char str1[128];
        char str2[128];
        char *p_addr,*c_addr;
        

       if((shmid=shmget(IPC_PRIVATE,1024,IPC_CREAT|0666))==-1)
      {
              printf(stderr,"Create Share Memory Error:%s\n");
        exit(1);
       }

      
       pid=fork();
      
      if(pid==0)
     {
        sleep(10);
        c_addr=shmat(shmid,0,0);
        i=0;
        while(1)
             {  
          if(*c_addr=='\n'||*c_addr==EOF)
          {
            str1[i]='\0';
            k=func(str1,str2);
            printf("%s\t",str1);
            if(k==1)
            {
             printf("Yes\n");
             i=0;
            }
            else
            {
             printf("No\n");
             i=0;
            }
            if(*c_addr==EOF) break;         
          }
          else
          {
            str1[i]=*c_addr;
            i++;
            c_addr++;
          }
            
        }
      shmdt(c_addr);
      exit(0);
     }//if(pid==0)
      if(pid>0)
      {   
         p_addr=shmat(shmid,0,0);
         printf("please enter the name of the file:\n");
         scanf("%s",filename);
         FILE *fp;
         fp=fopen(filename,"r");
         if(fp==NULL)
         {
          printf("file doesn't exist\n");
          exit(1);
         }
         while(1)
        {
                 ch=fgetc(fp);
                 if(count>1023)
                 {
                    printf("memory use out\n");
                    exit(1);
                 }               
          *p_addr=ch;
          p_addr++;
                 count++;
          if(ch==EOF)
                 {
            *p_addr='\0';
            fclose(fp);
            cid=wait(NULL);//等待子进程结束
            break;
          }
         
        }
        shmdt(p_addr);
        exit(0);
      }//if(pid>0)
     
      if(pid==-1)
     {
       printf(stderr,"Fork Error\n");
       exit(1);
     }
     printf("task finished\n");
     return 1;
}
[/code:1]

求教大虾
发表于 2003-11-2 22:13:25 | 显示全部楼层
当然了,c_addr跟p_addr不相等,
shmat每一次返回的内存都是当前内核可用内存的首地址,当然需要shmat里面指定的内存参数为0。
你要通过共享内存传信息的话,把父进程里面shmat返回的p_addr传给子进程即可。
回复

使用道具 举报

发表于 2003-11-3 11:14:13 | 显示全部楼层
不好意思,昨天晚上没有看明白,就胡说了一通。
今天又看了一下,在共享内存这块应该没有什么问题。
我改了一点:
[code]
int main(int argc,char **argv)
{
        int shmid;
   pid_t pid,cid;
        int count=0;
        int leng;
        int i,k;
        char ch='\0';
        char filename[20];
        char str1[128];
        char str2[128];
        char *p_addr,*c_addr;
        

       if((shmid=shmget(IPC_PRIVATE,1024,IPC_CREAT|0666))==-1)
      {
         printf(stderr,"Create Share Memory Error:%s\n");
        exit(1);
       }

        
       pid=fork();
        
      if(pid==0)
     {
        sleep(10);
        c_addr=shmat(shmid,0,0);
        i=0;
    /*    while(1)
        {  
         if(*c_addr=='\n'||*c_addr==EOF)
          {
            str1='\0';
            k=func(str1,str2);
            printf("%s\t",str1);
            if(k==1)
            {
             printf("Yes\n");
             i=0;
            }
            else
            {
             printf("No\n");
             i=0;
            }
            if(*c_addr==EOF) break;         
          }
          else
          {
            str1=*c_addr;
            i++;
            c_addr++;
          }
            
        }*/
      printf("c_addr's content: %s\n",c_addr);
      shmdt(c_addr);
      exit(0);
     }//if(pid==0)
      if(pid>0)
      {   
         p_addr=shmat(shmid,0,0);
         printf("please enter the name of the file:\n");
         scanf("%s",filename);
         FILE *fp;
         fp=fopen(filename,"r");
         if(fp==NULL)
         {
     printf("file doesn't exist\n");
          exit(1);
         }
         while(1)
        {
            ch=fgetc(fp);
            if(count>1023)
            {
               printf("memory use out\n");
               exit(1);
            }         
          *p_addr=ch;
          p_addr++;
            count++;
          if(ch==EOF)
            {
            *p_addr='\0';
            fclose(fp);
            cid=wait(NULL);//等待子进程结束
            break;
          }
         
        }
        shmdt(p_addr);
        exit(0);
      }//if(pid>0)
      
      if(pid==-1)
     {
       printf(stderr,"Fork Error\n");
       exit(1);
     }
     printf("task finished\n");
     return 1;
}
[\code]
我把子进程里面WHILE(1)那段注释掉了,然后用PRINTF()得到的内存内容应该是一样的,我试过了。
可能是WHILE(1)这段里面读内存的的时候出错了吧,没有弄明白那段代码的意思。只是执行的时候不停的出NO,我想那个判断语句IF(*C_ADDR==EOF) break 是不是没有起上作用。
还有一个问题就是,在父进程里面读的文件如果大的话,即COUNT大于1023,父进程是结束了,可是子进程并不结束,而且也是个死循环。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-9 10:47 , Processed in 0.050055 second(s), 15 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表