内存信号量sem_init函数解析

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
#include
#include
#include
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
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#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就可以了,后面不会执行
只有子进程(延迟解锁)解锁,才会继续进行


你可能感兴趣的:(Linux,System,Program)