69,382
社区成员
发帖
与我相关
我的任务
分享
#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;
}