进程&线程间通信:信号量

简介: 参考文档:http://blog.csdn.net/evsqiezi/article/details/8061176头文件:#includeint sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。

 

参考文档:http://blog.csdn.net/evsqiezi/article/details/8061176
头文件:#include<semaphore.h>

int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));
sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。

int sem_post(sem_t *sem);
用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的
成功时返回 0;错误时,信号量的值没有更改,-1 被返回,并设置errno 来指明错误

int sem_wait(sem_t * sem);
sem_wait函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对 一个值为2的信号量调用sem_wait(),线程将会继续执行,介信号量的值将减到1。如果对一个值为0的信号量调用sem_wait(),这个函数就 会地等待直到有其它线程增加了这个值使它不再是0为止

int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。在成功完成之后会返回零。其他任何返回值都表示出现了错误。

int sem_destroy (sem_t *sem);
用来释放信号量sem,属于无名信号量。 

sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value);
创建并初始化有名信号灯。
oflag参数可以是0、O_CREAT(创建一个信号灯)或O_CREAT|O_EXCL(如果没有指定的信号灯就创建),如果指定了O_CREAT,那么第三个和第四个参数是需要的;其中mode参数指定权限位,value参数指定信号灯的初始值,通常用来指定共享资源的书面。该初始不能超过SEM_VALUE_MAX,这个常值必须低于为32767。二值信号灯的初始值通常为1,计数信号灯的初始值则往往大于1。

int sem_close(sem_t *sem);
关闭有名信号灯。若成功则返回0,否则返回-1。一个进程终止时,内核还对其上仍然打开着的所有有名信号灯自动执行这样的信号灯关闭操作。不论该进程是自愿终止的还是非自愿终止的,这种自动关闭都会发生。但应注意的是关闭一个信号灯并没有将他从系统中删除。

int sem_unlink(const char *name);
若成功则返回0,否则返回-1。有名信号灯使用sem_unlink从系统中删除。每个信号灯有一个引用计数器记录当前的打开次数,sem_unlink必须等待这个数为0时才能把name所指的信号灯从文件系统中删除。也就是要等待最后一个sem_close发生。

 

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <semaphore.h>

#ifndef T_DESC
#define T_DESC(x, y)   (y)
#endif

#if T_DESC("TU1", 1)

sem_t my_sem1;
sem_t my_sem2;

void thread_1(void)  
{  
    int i;  
    for(i=0; i<10; i++)  {
        sem_wait(&my_sem1);
        printf("This is pthread_1.\n");  
        sleep(1);  
        printf("pthread_1 sleep ok.\n");
        sem_post(&my_sem2);
    }  
    pthread_exit(0);  
}  
  
void thread_2(void)  
{  
    int i;  
    for(i=0; i<10; i++) {
        sem_wait(&my_sem2);
        printf("This is pthread_2.\n");  
        sleep(2);  
        printf("pthread_2 sleep ok.\n");
        sem_post(&my_sem1);
    }  
    pthread_exit(0);  
}  
  
int tu1_proc(void)  
{  
    pthread_t id_1,id_2;  
    int i,ret;  

    //int sem_init(sem_t *sem, int pshared, unsigned int value);
    ret = sem_init(&my_sem1, 1, 0);
    if(ret != 0)  
    {  
        printf("sem_init error!\n");  
        return -1;  
    } 

    ret = sem_init(&my_sem2, 1, 1); //至少一个value为1,避免死锁
    if(ret != 0)  
    {  
        printf("sem_init error!\n");   
        return -1;  
    } 
    
    ret = pthread_create(&id_1, NULL, (void *)thread_1, NULL);  
    if(ret != 0)  
    {  
        printf("Create pthread error!\n");  
        return -1;  
    }  
    
    ret = pthread_create(&id_2, NULL, (void *)thread_2, NULL);  
    if(ret != 0)  
    {  
        printf("Create pthread error!\n");  
        return -1;  
    }  
    
    /*等待线程结束*/  
    pthread_join(id_1, NULL);  
    pthread_join(id_2, NULL);  

    sem_destroy(&my_sem1);
    sem_destroy(&my_sem2);
    
    return 0;  
}  
#endif

#if T_DESC("TU2", 1)
sem_t *my_shm_sem1;
sem_t *my_shm_sem2;

void thread_21(void)  
{  
    int i;  
    for(i=0; i<10; i++)  {
        sem_wait(my_shm_sem1);
        printf("This is pthread_1.\n");  
        sleep(1);  
        printf("pthread_1 sleep ok.\n");
        sem_post(my_shm_sem2);
    }  
    pthread_exit(0);  
}  
  
void thread_22(void)  
{  
    int i;  
    for(i=0; i<10; i++) {
        sem_wait(my_shm_sem2);
        printf("This is pthread_2.\n");  
        sleep(1);  
        printf("pthread_2 sleep ok.\n");
        sem_post(my_shm_sem1);
    }  
    pthread_exit(0);  
}  
  
int tu2_proc(int argc, char **argv)  
{  
    pthread_t id_1,id_2;  
    int i,ret;  
    int param;

    if (argc < 2) return 1;
    param = atoi(argv[1]);

    //sem_t *sem_open(const char *name,int oflag,mode_t mode,unsigned int value);
    my_shm_sem1 = sem_open("my_sem1", O_CREAT, 644, 0);
    if(my_shm_sem1 == 0)  
    {  
        printf("sem_open error!\n");  
        return -1;  
    } 

    my_shm_sem2 = sem_open("my_sem2", O_CREAT, 644, 1); //至少一个value为1,避免死锁
    if(my_shm_sem2 == 0)  
    {  
        printf("sem_init error!\n");  
        return -1;  
    } 

    if (param) {
        ret = pthread_create(&id_1, NULL, (void *)thread_21, NULL);  
    } else {
        ret = pthread_create(&id_2, NULL, (void *)thread_22, NULL);  
    }
    if(ret != 0)  
    {  
        printf("Create pthread error!\n");  
        return -1;  
    }  
    
    /*等待线程结束*/  
    if (param) {
        pthread_join(id_1, NULL);  
    } else {
        pthread_join(id_2, NULL);  
    }

    sem_close(my_shm_sem1);
    sem_close(my_shm_sem2);
    
    if (param ) {
        sem_unlink("my_sem1");
        sem_unlink("my_sem2");
    }
    
    return 0;  
}  

#endif

#if T_DESC("global", 1)
void usage()
{
    printf("\n Usage: <cmd> <tu> <p1> <...>");
    printf("\n   1 -- sem between thread");
    printf("\n   2 -- sem between process, need su mode");
    printf("\n     => P1: 0 - create pid 0; 1 - create pid 1");
    printf("\n");
}

int main(int argc, char **argv)
{
    int ret;
    
    if(argc < 2) {
        usage();
        return 0;
    }

    int tu = atoi(argv[1]);
    if (tu == 1) ret = tu1_proc();
    if (tu == 2) ret = tu2_proc(argc - 1, &argv[1]);
    
    return ret;
}
#endif

#if T_DESC("readme", 1)
/*
1, how to compile 
gcc -o usem.out usem.c -lpthread
gcc -g -o usem.out usem.c -lpthread

*/
#endif

 

目录
相关文章
|
3天前
|
Linux
【Linux】命名管道的创建方法&&基于命名管道的两个进程通信的实现
【Linux】命名管道的创建方法&&基于命名管道的两个进程通信的实现
|
2天前
|
Java 测试技术 Python
Python的多线程允许在同一进程中并发执行任务
【5月更文挑战第17天】Python的多线程允许在同一进程中并发执行任务。示例1展示了创建5个线程打印&quot;Hello World&quot;,每个线程调用同一函数并使用`join()`等待所有线程完成。示例2使用`ThreadPoolExecutor`下载网页,创建线程池处理多个URL,打印出每个网页的大小。Python多线程还可用于线程间通信和同步,如使用Queue和Lock。
14 1
|
2天前
|
缓存 算法 Java
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)(4)
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)
16 0
|
2天前
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)(3)
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)
13 0
|
2天前
|
C++ 调度
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)(2)
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)
13 0
|
2天前
|
算法 安全 调度
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)(1)
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)
14 0
操作系统(8)---进程的同步与互斥以及信号量机制(万字总结~)(1)
|
2天前
|
数据处理 Python
Python并发编程:实现高效的多线程与多进程
Python作为一种高级编程语言,提供了强大的并发编程能力,通过多线程和多进程技术,可以实现程序的并发执行,提升系统的性能和响应速度。本文将介绍Python中多线程和多进程的基本概念,以及如何利用它们实现高效的并发编程,解决实际开发中的并发性问题。
|
3天前
内存映射实现父子进程通信
内存映射实现父子进程通信
|
3天前
利用命名管道实现任意进程间的通信
利用命名管道实现任意进程间的通信
|
3天前
|
Unix Linux 调度
linux线程与进程的区别及线程的优势
linux线程与进程的区别及线程的优势