int sem_init(sem_t *sem, int pshared, unsigned int value);
return 0 on success,or -1 on error
本文着重解析sem_init第二个参数 pshared ,下面摘自《The Linux Programming Interface》
这一段大体意思:如果pshared是0 则可以在线程间共享
如果非0,则可以在进程间共享,但是有个条件:信号量必须存在于共享内存中
也就是说并非pshared非0就可以实现进程间共享,示例如下:
#include <stdio.h>
#include <errno.h>
#include <semaphore.h>
#include <fcntl.h>
sem_t sem;
static void mysem(char *str)
{
int i = 0;
while('\0' != str[i])
{
printf("%c\n", str[i++]);
sleep(1);
}
}
int main(void)
{
pid_t pid = -1;
int ret = -1;
int status = -1;
int semvalue;
sem_init(&sem,0,1);
pid = fork();
if(-1 == (ret = pid))
{
perror("fork failed: ");
goto _OUT;
}
if(0 == pid)
{
mysem("abcd");
printf("2sem address is %x\r\n",&sem);
sem_getvalue(&sem,&ret);
printf("1sem ret is %d\r\n",ret);
ret = sem_post(&sem);
sem_getvalue(&sem,&ret);
printf("2sem ret is %d\r\n",ret);
ret = sem_post(&sem);
sem_getvalue(&sem,&ret);
printf("2.5sem ret is %d\r\n",ret);
}
if(0 < pid)
{
printf("1sem address is %x\r\n",&sem);
wait(&status);
sem_getvalue(&sem,&ret);
printf("3sem ret is %d\r\n",ret);
ret = sem_wait(&sem);
mysem("1234");
ret = sem_wait(&sem);
sem_getvalue(&sem,&ret);
printf("4sem ret is %d\r\n",ret);
mysem("5678");
sem_destroy(&sem);
}
_OUT:
return ret;
}
[meteor@localhost sem]$ ./sem_ram_syn
1sem address is 804a044
a
b
c
d
2sem address is 804a044
1sem ret is 1
2sem ret is 2
2.5sem ret is 3
3sem ret is 1
1
2
3
4
^C
仔细分析打印结果可以发现,父进程(pid>0)中sem的值只与sem_init初始化的值有关,不管子进程中
有多少次post,父进程依然会锁住,并不会打印“5678”
具体进程间共享暂未实现,有时间再补上
线程间共享:
#include <stdio.h>
#include <errno.h>
#include <semaphore.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#define SEM_NAME "mysem"
#define OPEN_FLAG O_RDWR|O_CREAT
#define OPEN_MODE 00777
#define INIT_V 0
sem_t sem;
static void mysem(char *str)
{
int i = 0;
while('\0' != str[i])
{
printf("%c\n", str[i++]);
sleep(1);
}
}
void *thrd_func()
{
int ret = -1;
mysem("abcd");
sem_getvalue(&sem,&ret);
printf("1sem ret is %d\r\n",ret);
ret = sem_post(&sem);
sem_getvalue(&sem,&ret);
printf("2sem ret is %d\r\n",ret);
ret = sem_post(&sem);
sem_getvalue(&sem,&ret);
printf("2.5sem ret is %d\r\n",ret);
}
int main(void)
{
pid_t pid = -1;
int ret = -1;
int status = -1;
int semvalue;
pthread_t tid;
sem_init(&sem,0,0);
pthread_create(&tid,NULL, thrd_func, NULL);
sleep(10);
sem_getvalue(&sem,&ret);
printf("3sem ret is %d\r\n",ret);
ret = sem_wait(&sem);
sem_getvalue(&sem,&ret);
printf("4sem ret is %d\r\n",ret);
mysem("1234");
ret = sem_wait(&sem);
sem_getvalue(&sem,&ret);
printf("5sem ret is %d\r\n",ret);
mysem("5678");
sem_destroy(&sem);
return 0;
}
[meteor@localhost sem]$ ./sem_ram_thread
a
b
c
d
1sem ret is 0
2sem ret is 1
2.5sem ret is 2
3sem ret is 2
4sem ret is 1
1
2
3
4
5sem ret is 0
5
6
7
8
[meteor@localhost sem]$
线程间用锁
#include <stdio.h>
#include <errno.h>
#include <semaphore.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#define SEM_NAME "mysem"
#define OPEN_FLAG O_RDWR|O_CREAT
#define OPEN_MODE 00777
#define INIT_V 0
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
sem_t sem;
static void mysem(char *str)
{
int i = 0;
while('\0' != str[i])
{
printf("%c\n", str[i++]);
sleep(1);
}
}
void *thrd_func()
{
int ret = -1;
pthread_mutex_unlock(&mutex);
pthread_mutex_unlock(&mutex);
mysem("abcd");
sleep(20);
pthread_mutex_unlock(&mutex);
}
int main(void)
{
pid_t pid = -1;
int ret = -1;
int status = -1;
int semvalue;
pthread_t tid;
pthread_create(&tid,NULL, thrd_func, NULL);
sleep(10);
pthread_mutex_lock(&mutex);
mysem("1234");
pthread_mutex_lock(&mutex);
mysem("5678");
sem_destroy(&sem);
return 0;
}
[meteor@localhost sem]$ ./lock_thread
a
b
c
d
1
2
3
4
5
6
7
8
[meteor@localhost sem]$
可见,跟信号量不同的一点,子线程不管解锁多少次,主线程一次lock就可以了,后面不会执行
只有子进程(延迟解锁)解锁,才会继续进行