#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <linux/ipc.h>
#include <linux/shm.h>
#include <sys/stat.h>
#include <linux/sem.h>
#include <sys/wait.h>
/*將以上頭文件 shm.h types.h ipc.h stat.h 中sys改爲linux後,許多奇怪的redefinition錯誤消失了*/
#define file_op_size 128
#define shared_segment_size 1024
void P(int semid,int index)
{
struct sembuf sem;
sem.sem_num=index;
sem.sem_op=-1;
sem.sem_flg=0; //操作標記 0或IPC_NOWAIT等
semop(semid,&sem,1); //1:表示執行命令的個數
return;
}
void V(int semid,int index)
{
struct sembuf sem;
sem.sem_num=index;
sem.sem_op=1;
sem.sem_flg=0; //操作標記 0或IPC_NOWAIT等
semop(semid,&sem,1); //1:表示執行命令的個數
return;
}
int main()
{
int status;
char s_filename[20]="source";
char d_filename[20]="destination";
int segment_id[10]; //10個共享內存塊
struct shmid_ds shmbuffer;
int segment_size;
int ret;
key_t num = 5630;
pid_t p_r; //讀進程號
pid_t p_w; //寫進程號
char *shmaddr1;
int i=0;
FILE *fp1=NULL;
char *shmaddr2;
int j=0;
FILE *fp2=NULL;
//獲取文件長度
FILE *end_p=NULL;
long length;
end_p=fopen(s_filename,"r"); //以只讀方式打開文件,該文件必須存在。
fseek(end_p,0L,SEEK_END); //把文件的位置指針移到文件尾(第三個參數爲從哪裏開始偏移)
length=ftell(end_p); //獲取文件長度
fclose(end_p);
printf("文件長度爲%ld!\n",length);
//char *shared_memory;
//創建10個共享內存塊
for(int i=0;i<10;i++)
{
segment_id[i]=shmget(/*(key_t)num++*/IPC_PRIVATE,/*shared_segment_size*/1024,IPC_CREAT|0666); //int shmget(key_t key, size_t size, int shmflg)
if(segment_id[i]<0)
{
printf("shmget error\n");
return -1;
}
printf("creat the shared_memory:%d\n",segment_id[i]);
/*確定內存塊的大小*/
ret=shmctl(segment_id[i],IPC_STAT,&shmbuffer);
if(ret!=0)
{
printf("shmctl error!\n");
return -1;
}
segment_size=shmbuffer.shm_segsz;
printf("segment size:%d\n",segment_size); //這裏輸出的是0!!!
}
//創建信號燈
int semid = semget(0,2,IPC_CREAT|0666); //創建了2個信號燈
//信號燈賦值
union semun sem_args1;
sem_args1.val=10;
ret = semctl(semid,0,SETVAL,sem_args1); //0:第一個信號燈,可寫的個數
union semun sem_args2;
sem_args2.val=0;
ret = semctl(semid,1,SETVAL,sem_args2); //1:第二個信號燈,可讀的個數
p_r=fork();
if(p_r==0)
{
fp1=fopen(s_filename,"rb+");
if(fp1==NULL)
{
printf("file_open_error1!\n");
return -1;
}
// long offset=0;
//printf("sizeof shmaddr:%d\n",sizeof(shmaddr1));
printf("讀進程開始進入循環!\n");
while(1)
{
P(semid,0); //申請一個可寫的信號燈(內存塊)
shmaddr1=(char *)shmat(segment_id[i],NULL,SHM_R | SHM_W); //綁定到內存共享塊
//shmaddr1=(char *)shmaddr1;
printf("讀進程已綁定到內存共享塊%d!shmaddr1:%p\n",i,shmaddr1);
/*確定內存塊的大小*/
shmctl(segment_id[i],IPC_STAT,&shmbuffer);
segment_size=shmbuffer.shm_segsz;
printf("segment size:%d\n",segment_size); //這裏輸出的是0!!!
printf("1\n");
char temp[100];
//printf("sizeof char*: %d,sizeof shmaddr:%d\n",sizeof(temp),sizeof(shmaddr));
fread(shmaddr1,1,1,fp1); //讀數據到內存塊
printf("1\n");
printf("讀進程已讀書據到內存共享塊%d!\n",i);
shmdt(shmaddr1); //斷開連接
V(semid,1); //添加一個可讀信號燈(內存塊)
i=(i+1)%10; //0-9 9+1=0
if(ftell(fp1)==length) //到文件尾跳出
break;
}
fclose(fp1);
printf("讀進程退出!\n");
return 0;
}
p_w=fork();
if(p_w==0)
{
fp2=fopen(d_filename,"w+"); //
if(fp2==NULL)
{
printf("file_open_error2!\n");
return -1;
}
printf("sizeof shmaddr:%d\n",sizeof(shmaddr2));
printf("寫進程開始進入循環!\n");
while(1)
{
P(semid,1); //申請一個可讀信號燈(內存塊)
shmaddr2=(char *)shmat(segment_id[j],NULL,SHM_R | SHM_W); //綁定到內存共享塊
printf("寫進程已綁定到內存共享塊%d!\n",i);
strcpy(shmaddr2,"Hi,I am child pocess!\n");
printf("%s\n", shmaddr2);
fwrite(shmaddr2,1,file_op_size,fp2);
printf("寫進程已從內存共享塊%d寫入到文件!\n",i);
shmdt(shmaddr2); //斷開連接
V(semid,0); //添加一個可寫信號燈(內存塊)
j=(j+1)%10; //0-9 9+1=0
if(ftell(fp2)==length) //到文件尾跳出
break;
}
fclose(fp2);
printf("寫進程退出!\n");
return 0;
}
waitpid(p_w,&status,0);
waitpid(p_r,&status,0);
//destroy10個共享內存塊
for(int i=0;i<10;i++)
{
shmctl(segment_id[i],IPC_RMID,0);
printf("creat the shared_memory:%d\n",i);
}
// 刪除信號燈
ret =semctl(semid,1,IPC_RMID);
printf("主進程退出!\n");
return 0;
}
終於找到問題了,頭文件改爲:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/sem.h> //!!!can't use linux!!!
#include <sys/wait.h>
就好了,真是GG,原因大概 是系統版本不一樣,系統自帶的頭文件的內容也不太一樣,具體要找到頭文件自己看內容