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

简介: 参考文档: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

 

目录
相关文章
|
2月前
|
调度 开发者 Python
深入浅出操作系统:进程与线程的奥秘
在数字世界的底层,操作系统扮演着不可或缺的角色。它如同一位高效的管家,协调和控制着计算机硬件与软件资源。本文将拨开迷雾,深入探索操作系统中两个核心概念——进程与线程。我们将从它们的诞生谈起,逐步剖析它们的本质、区别以及如何影响我们日常使用的应用程序性能。通过简单的比喻,我们将理解这些看似抽象的概念,并学会如何在编程实践中高效利用进程与线程。准备好跟随我一起,揭开操作系统的神秘面纱,让我们的代码运行得更加流畅吧!
|
22小时前
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
17天前
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
53 16
|
1月前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
146 20
|
1月前
|
消息中间件 调度
如何区分进程、线程和协程?看这篇就够了!
本课程主要探讨操作系统中的进程、线程和协程的区别。进程是资源分配的基本单位,具有独立性和隔离性;线程是CPU调度的基本单位,轻量且共享资源,适合并发执行;协程更轻量,由程序自身调度,适合I/O密集型任务。通过学习这些概念,可以更好地理解和应用它们,以实现最优的性能和资源利用。
66 11
|
1月前
|
Java Linux 调度
硬核揭秘:线程与进程的底层原理,面试高分必备!
嘿,大家好!我是小米,29岁的技术爱好者。今天来聊聊线程和进程的区别。进程是操作系统中运行的程序实例,有独立内存空间;线程是进程内的最小执行单元,共享内存。创建进程开销大但更安全,线程轻量高效但易引发数据竞争。面试时可强调:进程是资源分配单位,线程是CPU调度单位。根据不同场景选择合适的并发模型,如高并发用线程池。希望这篇文章能帮你更好地理解并回答面试中的相关问题,祝你早日拿下心仪的offer!
42 6
|
2月前
|
消息中间件 Unix Linux
【C语言】进程和线程详解
在现代操作系统中,进程和线程是实现并发执行的两种主要方式。理解它们的区别和各自的应用场景对于编写高效的并发程序至关重要。
92 6
|
2月前
|
调度 开发者
深入理解:进程与线程的本质差异
在操作系统和计算机编程领域,进程和线程是两个核心概念。它们在程序执行和资源管理中扮演着至关重要的角色。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
90 5
|
2月前
|
算法 调度 开发者
深入理解操作系统:进程与线程的管理
在数字世界的复杂编织中,操作系统如同一位精明的指挥家,协调着每一个音符的奏响。本篇文章将带领读者穿越操作系统的幕后,探索进程与线程管理的奥秘。从进程的诞生到线程的舞蹈,我们将一起见证这场微观世界的华丽变奏。通过深入浅出的解释和生动的比喻,本文旨在揭示操作系统如何高效地处理多任务,确保系统的稳定性和效率。让我们一起跟随代码的步伐,走进操作系统的内心世界。
|
2月前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
95 4

相关实验场景

更多