原理:
Server进程:
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define PERR(msg) do { perror(msg); exit(-1); } while(0)
#define PPERR(err,msg) do { err=errno; perror(msg); exit(-1); } while(0)
struct ticket
{
int remain;
pthread_mutex_t lock;
};
// 打印mutex的 进程共享属性
void printshared(pthread_mutexattr_t *attr)
{
int err,shared;
err = pthread_mutexattr_getpshared(attr,&shared);
if (err != 0) PPERR(err,"pthread_mutexattr_getshared");
if (shared == PTHREAD_PROCESS_PRIVATE)
puts("shared = PTHREAD_PROCESS_PRIVATE");
else if (shared == PTHREAD_PROCESS_SHARED)
puts("shared = PTHREAD_PROCESS_SHARED");
else
puts("shared = ???");
return;
}
// 打印mutex的 健壮属性
void printrobust(pthread_mutexattr_t *attr)
{
int err,robust;
err = pthread_mutexattr_getrobust(attr,&robust);
if (err != 0) PPERR(err,"pthread_mutexattr_getrobust");
if (robust == PTHREAD_MUTEX_STALLED)
puts("robust = PTHREAD_MUTEX_STALLED");
else if (robust == PTHREAD_MUTEX_ROBUST)
puts("robust = PTHREAD_MUTEX_ROBUST");
else
puts("robust = ???");
return;
}
int main(int argc, char **argv)
{
int err,shared;
int done = 0;
// genernate key_t type 0x5axxxxxx
key_t key = ftok(".",0x5a);
int id = shmget(key,getpagesize(),IPC_CREAT | IPC_EXCL | 0666);
if (id < 0) PERR("shmget");
struct ticket *t = (struct ticket *)shmat(id,NULL,0);
if (t == (void *)-1) PERR("shmat");
t->remain = 10;
pthread_mutexattr_t mutexattr;
err = pthread_mutexattr_init(&mutexattr);
if (err != 0) PPERR(err,"pthread_mutexattr_init");
printshared(&mutexattr);
printrobust(&mutexattr);
shared = PTHREAD_PROCESS_SHARED;
err = pthread_mutexattr_setpshared(&mutexattr,shared);
if (err != 0) PPERR(err,"pthread_mutexattr_setpshared");
err = pthread_mutexattr_setrobust(&mutexattr,PTHREAD_MUTEX_ROBUST);
if (err != 0) PPERR(err,"pthread_mutexattr_setrobust");
puts("modify attribute ----------------------");
printshared(&mutexattr);
printrobust(&mutexattr);
pthread_mutex_init(&t->lock,&mutexattr);
while(!done)
{
sleep(1);
printf("server remain %d.\n", t->remain);
}
err = pthread_mutex_destroy(&t->lock);
if (err != 0) PPERR(err,"pthread_mutex_destroy");
err = pthread_mutexattr_destroy(&mutexattr);
if (err != 0) PPERR(err,"pthread_mutexattr_destroy");
err = shmdt((void *)t);
if (err != 0) PERR("shmdt");
err = shmctl(id,IPC_RMID,NULL);
if (err != 0) PERR("shmctl");
return 0;
}
client1.c
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#define PERR(msg) do { perror(msg); exit(-1); } while(0)
#define PPERR(err,msg) do { err=errno; perror(msg); exit(-1); } while(0)
struct ticket
{
int remain;
pthread_mutex_t lock;
};
int main(int argc,char *argv[])
{
key_t key = ftok(".",0x5a);
if (argc < 2)
{
printf("Usage: %s <name>\n",argv[0]);
exit(-1);
}
char *name = argv[1];
int err,shared,flag = 1;
int id = shmget(key,0,0);
if (id < 0) PERR("shmget");
struct ticket *t = (struct ticket*)shmat(id,NULL,0);
if (t == (void *)-1) PERR("shmat");
while (flag)
{
err = pthread_mutex_lock(&t->lock);
// 需要恢复的成功
if (err == EOWNERDEAD)
{
puts("EOWNERDEAD");
// 拥有互斥锁的进程终止后,互斥量就变成inconsistent(不一致性)
// 恢复锁的一致性,此时进程还是获得锁的状态
err = pthread_mutex_consistent(&t->lock);
if (err != 0)
{
printf("consistent error\n");
exit(-1);
}
}
// 失败
else if (err == ENOTRECOVERABLE)
{
puts("ENOTRECOVERABLE");
}
// 不需要恢复的成功
int remain = t->remain;
if (remain > 0)
{
sleep(1);
--remain;
t->remain = remain;
printf("%s buy a ticket\n",name);
sleep(3);
} else
flag = 0;
pthread_mutex_unlock(&t->lock);
sleep(2);
}
err = shmdt((void *)t);
if (err != 0) PERR("shmdt");
return 0;
}
client2.c
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#define PERR(msg) do { perror(msg); exit(-1); } while(0)
#define PPERR(err,msg) do { err=errno; perror(msg); exit(-1); } while(0)
struct ticket
{
int remain;
pthread_mutex_t lock;
};
int main(int argc,char *argv[])
{
key_t key = ftok(".",0x5a);
if (argc < 2)
{
printf("Usage: %s <name>\n",argv[0]);
exit(-1);
}
char *name = argv[1];
int err,shared,flag = 1;
int id = shmget(key,0,0);
if (id < 0) PERR("shmget");
struct ticket *t = (struct ticket*)shmat(id,NULL,0);
if (t == (void *)-1) PERR("shmat");
while (flag)
{
err = pthread_mutex_lock(&t->lock);
// 需要恢复的成功
if (err == EOWNERDEAD)
{
puts("EOWNERDEAD");
// 拥有互斥锁的进程终止后,互斥量就变成inconsistent(不一致性)
// 恢复锁的一致性,此时进程还是获得锁的状态
err = pthread_mutex_consistent(&t->lock);
if (err != 0)
{
printf("consistent error\n");
exit(-1);
}
}
// 失败
else if (err == ENOTRECOVERABLE)
{
puts("ENOTRECOVERABLE");
}
// 不需要恢复的成功
int remain = t->remain;
if (remain > 0)
{
sleep(1);
--remain;
t->remain = remain;
printf("%s buy a ticket\n",name);
sleep(3);
} else
flag = 0;
pthread_mutex_unlock(&t->lock);
sleep(2);
}
err = shmdt((void *)t);
if (err != 0) PERR("shmdt");
return 0;
}
Makefile:
all:
gcc -g server.c -o server -lpthread
gcc -g client1.c -o client1 -lpthread
gcc -g client2.c -o client2 -lpthread
clean:
rm -fr server client1 client2
测试:
用到的几个pthread函数:
ftok的实现:
结束!