linux CentOS下的C语言异步访问共享内存问题,高手请进!

luvi88 2010-09-13 08:29:41

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <semaphore.h>

#define USE_SEMAPHORE 1
#define OAM_FTOK_ID 8
#define N 10
#define NUM_PROCESS 2

typedef struct {
char name[8];
char age;
char sex;
short id;
} student_t;

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

/* global variable */
//sem_t mutex;
int sem_id; // semaphore

void display(const student_t const *buf, const int n);
int child_process(const void *buf, const int len);
//int child_process(void *buf, int len, sem_t *pmutex);
static int set_semvalue(void);
static void del_semvalue(void);
static int semaphore_p(void);
static int semaphore_v(void);
void modify(student_t *buf, const int start, const int n);
int main(int argc, char **argv)
{
int id;
int i;
int pid;
int fd;
student_t *buf;
// student_t *p;

id = ftok(*argv, OAM_FTOK_ID);
if (-1 == id)
{
perror("ftok");
return -1;
}

/* initialize semaphore */
/* if (-1 == sem_init(&mutex, 0, 1))
{
perror("sem_init");
exit(-3);
}
*/
sem_id = semget(id, 1, 0600|IPC_CREAT);
if (-1 == sem_id)
{
perror("semget");
exit(-4);
}
if (set_semvalue())
{
fprintf(stderr, "%s: semctl", __FUNCTION__);
exit(-5);
}

// p = (student_t *)malloc(N * sizeof(student_t));
fd = open("ccccccccccccc.txt", O_CREAT | O_RDWR | O_TRUNC, 00666);
ftruncate(fd, N * sizeof(student_t));
buf = (student_t *)mmap(NULL, N*sizeof(student_t), \
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
printf("buf = %p\n", buf);
if (NULL == buf)
{
perror("mmap");
return -1;
}

/* init */
puts("Init:");
for (i=0; i<N; i++)
{
buf[i].name[0] = 'a'+i;
buf[i].name[1] = '\0';
buf[i].age = 20+i;
buf[i].sex = i % 2;
buf[i].id = (short) i;
}

display(buf, N);

for (i=0; i<NUM_PROCESS; i++)
{

pid = fork();
if (pid < 0)
{
perror("fork");
exit(-2);
}
else if (0 == pid)
{ // child, modify or display result
student_t *pbuf;

/* remap share memory */
fd = open("ccccccccccccc.txt", O_CREAT | O_RDWR | O_TRUNC, 00666);
ftruncate(fd, N * sizeof(student_t));
pbuf = (student_t *)mmap(NULL, N*sizeof(student_t), \
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (NULL == pbuf)
{
perror("mmap");
return -1;
}
printf("Child: pbuf = %p\n", pbuf);

if (1 == i)
{ // show result
sleep(3);
display(pbuf, N);
}
else
{ // update data in share memory
modify(pbuf, 'A', N);
}
// child_process(pbuf, N);
// child_process(pbuf, N, &mutex);
munmap(pbuf, N*sizeof(student_t));
// free(p);
close(fd);
exit(1);
}
else
{ // Father, waiting for children
/*
sleep(1);
// sem_wait(&mutex);
for (i=0; i<N; i++)
{
buf[i].name[0] = 'A'+i;
buf[i].name[1] = '\0';
buf[i].age = 20+i;
buf[i].sex = i % 2;
buf[i].id = (short) i;
}
puts("Father 2:");
// sem_post(&mutex);
display(buf, N);
wait(NULL);
*/
int status;
pid = waitpid(pid, &status, 0);
fprintf(stderr, "[pid: %d], status: %d\n", pid, status);
}
} // end for

puts("Father(After ending children):");
printf("&buf == %p\n", buf);
display(buf, N);
del_semvalue();
munmap((void *)buf, N * sizeof(student_t));
close(fd);
// sem_destroy(&mutex);
// free(p);
return 0;
}

void display(const student_t const *buf, const int n)
{
int i;

semaphore_p();
printf("[%d] Result:\n", getpid());
for (i=0; i<n; i++)
{
printf("{(%d)\tid: %d, name: %s, age: %d, sex: %d}\n", \
getpid(), buf[i].id, buf[i].name, buf[i].age, buf[i].sex);
usleep(50000);
}
printf("&buf.name = %p\n", buf[0].name);
semaphore_v();
}

void modify(student_t *buf, const int start, const int n)
{
int i;

/* init */
semaphore_p();
printf("[%d] Updating:\n", getpid());
for (i=start; i<start+n; i++)
{
buf[i].name[0] = i;
buf[i].name[1] = '\0';
buf[i].age = 20+i;
buf[i].sex = i & 1;
buf[i].id = (short) i;
printf("[%p] '%s'\n", buf[i].name, buf[i].name);
usleep(50000);
}
semaphore_v();
printf("[%d]: name: %s\n", getpid(), buf[0].name);
display(buf, n);
}

int child_process(const void *buf, const int len)
//int child_process(void *buf, int len, sem_t *pmutex)
{
// sem_wait(&mutex);
puts("child 1:");
display(buf, len);
// sem_post(&mutex);
sleep(2);
// sem_wait(&mutex);
puts("child 2:");
display(buf, len);
// sem_post(&mutex);

return 0;
}

static int set_semvalue(void)
{
union semun sem_union;

sem_union.val = 1;
if (-1 == semctl(sem_id, 0, SETVAL, sem_union))
{
return -1;
}

return 0;
}

static void del_semvalue(void)
{
union semun sem_union;

if (-1 == semctl(sem_id, 0, IPC_RMID, sem_union))
{
perror("semctl");
}
}

static int semaphore_p(void)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
if (-1 == semop(sem_id, &sem_b, 1))
{
perror("semop");
return -1;
}

return 0;
}

static int semaphore_v(void)
{
struct sembuf sem_b;

sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if (-1 == semop(sem_id, &sem_b, 1))
{
perror("semop");
return -1;
}

return 0;
}



#if 0
在CentOS 4.8 平台上,运行结果如下:

/************************* 运行结果 ***************************/
[root@reduce aa]# ./a.out
buf = 0xb7fff000
Init:
[3810] Result:
{(3810) id: 0, name: a, age: 20, sex: 0}
{(3810) id: 1, name: b, age: 21, sex: 1}
{(3810) id: 2, name: c, age: 22, sex: 0}
{(3810) id: 3, name: d, age: 23, sex: 1}
{(3810) id: 4, name: e, age: 24, sex: 0}
{(3810) id: 5, name: f, age: 25, sex: 1}
{(3810) id: 6, name: g, age: 26, sex: 0}
{(3810) id: 7, name: h, age: 27, sex: 1}
{(3810) id: 8, name: i, age: 28, sex: 0}
{(3810) id: 9, name: j, age: 29, sex: 1}
&buf.name = 0xb7fff000
Child: pbuf = 0xb7ffd000
[3811] Updating:
[0xb7ffd30c] 'A'
[0xb7ffd318] 'B'
[0xb7ffd324] 'C'
[0xb7ffd330] 'D'
[0xb7ffd33c] 'E'
[0xb7ffd348] 'F'
[0xb7ffd354] 'G'
[0xb7ffd360] 'H'
[0xb7ffd36c] 'I'
[0xb7ffd378] 'J'
[3811]: name:
[3811] Result:
{(3811) id: 0, name: , age: 0, sex: 0}
{(3811) id: 0, name: , age: 0, sex: 0}
{(3811) id: 0, name: , age: 0, sex: 0}
{(3811) id: 0, name: , age: 0, sex: 0}
{(3811) id: 0, name: , age: 0, sex: 0}
{(3811) id: 0, name: , age: 0, sex: 0}
{(3811) id: 0, name: , age: 0, sex: 0}
{(3811) id: 0, name: , age: 0, sex: 0}
{(3811) id: 0, name: , age: 0, sex: 0}
{(3811) id: 0, name: , age: 0, sex: 0}
&buf.name = 0xb7ffd000
[pid: 3811], status: 256
Child: pbuf = 0xb7ffd000
[3812] Result:
{(3812) id: 0, name: , age: 0, sex: 0}
{(3812) id: 0, name: , age: 0, sex: 0}
{(3812) id: 0, name: , age: 0, sex: 0}
{(3812) id: 0, name: , age: 0, sex: 0}
{(3812) id: 0, name: , age: 0, sex: 0}
{(3812) id: 0, name: , age: 0, sex: 0}
{(3812) id: 0, name: , age: 0, sex: 0}
{(3812) id: 0, name: , age: 0, sex: 0}
{(3812) id: 0, name: , age: 0, sex: 0}
{(3812) id: 0, name: , age: 0, sex: 0}
&buf.name = 0xb7ffd000
[pid: 3812], status: 256
Father(After ending children):
&buf == 0xb7fff000
[3810] Result:
{(3810) id: 0, name: , age: 0, sex: 0}
{(3810) id: 0, name: , age: 0, sex: 0}
{(3810) id: 0, name: , age: 0, sex: 0}
{(3810) id: 0, name: , age: 0, sex: 0}
{(3810) id: 0, name: , age: 0, sex: 0}
{(3810) id: 0, name: , age: 0, sex: 0}
{(3810) id: 0, name: , age: 0, sex: 0}
{(3810) id: 0, name: , age: 0, sex: 0}
{(3810) id: 0, name: , age: 0, sex: 0}
{(3810) id: 0, name: , age: 0, sex: 0}
&buf.name = 0xb7fff000
/********************************* 运行结果结束 *******************************/

结果分析:
也就是说,父进程初始化结束,对共享内存的内容产生了影响。
在子进程中的修改结果只在for修改语句中有效,出了这个for语句之后,
子进程对自身重映射的共享内存的修改结果就无效了。
并且在子进程中,也影响了父进程共享内存的内容,导致其内容丢失。
请高手分析和指出错误并加以指正,泪奔式谢谢广大童鞋了!

#endif
...全文
104 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
luvi88 2010-09-16
  • 打赏
  • 举报
回复
没有人有耐心吗?
luvi88 2010-09-14
  • 打赏
  • 举报
回复
谢谢了,因为只是一小测试,没有写注释,发贴的时候,应该把注释加上的。。。。
最下边4个接口分别是信号量操作的。
static int set_semvalue(void); /* 设置信号量的值 */
static void del_semvalue(void); /* 删除信号量 */
static int semaphore_p(void); /* 信号量p操作 */
static int semaphore_v(void); /* v操作 */
int child_process(const void *buf, const int len); /* 此接口无用,是单子进程时用的,双子进程时,使用下边两个接口访问共享内存: */
void display(const student_t const *buf, const int n); /* 互斥显示共享内存内容 */
void modify(student_t *buf, const int start, const int n); /* 互斥修改共享内存内容 */
zecard_fu 2010-09-13
  • 打赏
  • 举报
回复
实在下不起决心看完! 友情帮顶下好了~
luvi88 2010-09-13
  • 打赏
  • 举报
回复
附注
当只有父亲和一个孩子的时候,结果是正确的。两个孩子的时候,这两个孩子相互没有父子性亲缘关系了,问题就出来了。。。

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧