Linux下的sem_wait等待函数简介 (linux sem wait)

在Linux操作系统中,进程间同步和互斥的机制有许多种,其中最常用的是信号量(Semaphore)。信号量是由Dijkstra首次引入的一种系统结构,其本质是一把锁,用于保护共享资源。在经典的生产者-消费者问题中,生产者和消费者进程之间需要共享一个缓冲区,因此需要使用信号量来保证缓冲区的正确性。

而在使用信号量时,一个非常重要的函数是sem_wt函数。这个函数的作用是阻塞当前进程,直到某一个信号量的值变得大于0。而当一个进程对信号量执行减操作时,如果信号量的值为0,那么该进程就会被阻塞,直到另外一个进程对信号量执行加操作将其值变为非0。

sem_wt的函数原型如下:

int sem_wt(sem_t *sem);

其中sem_t是一个信号量类型,表示一个信号量的实例,*sem则是具体的信号量变量。sem_wt函数的返回值为0表示函数执行成功;否则,就表示函数执行失败。

在实际使用时,sem_wt函数常常与sem_post函数配合使用。sem_post函数是另外一个信号量函数,用于增加信号量的值。通过调用sem_post函数,我们可以将一个被阻塞的进程唤醒,从而使其继续执行。注意:sem_wt和sem_post函数只能用于已经初始化的信号量上,否则将出现系统错误。

一般情况下,sem_wt函数是在临界区中调用的。在许多并发程序中,临界区是程序中需要互斥访问的临界资源,在进入临界区之前,应该对临界区进行加锁,当退出临界区时,再释放锁。sem_wt函数可以保证临界区不会同时被多个进程占用,从而保证临界区的数据正确性和一致性。

在信号量的应用中,sem_wt函数被广泛地用于等待共享资源的可用性。举例来说,假设有10个进程需要访问一个共享变量,但是这个变量只能同时被一个进程访问。这时,我们就可以使用一个信号量来实现对共享变量的互斥访问控制。当一个进程访问共享变量之前,需要获取信号量的内部资源,如果相应的信号量取得资源的量为0,则进程需要一直等待,直到资源可用。

sem_wt函数是Linux环境下实现进程同步和互斥机制的重要函数之一。通过使用这个函数,我们可以更加精确地控制进程的执行顺序和访问共享资源的安全性。对于需要进行并发编程的开发者来说,熟练掌握sem_wt函数的使用方法,是非常关键的一环。

相关问题拓展阅读:

linux 信号量问题 编译错误 好像不识别sem_t定义的变量

帮你修改了一手搭下,编译运行没问题,修改的地方都标出来了,

由于不知道你程序的功能袜薯老,所以没有对你的程序逻辑进行分析

#include

#include

#include

#include

//–以下是修改的部分

sem_t in;

sem_t out;

sem_t handout;

sem_t handin;

sem_t goout;

//–

int counter=0;

void * studentIn(void *a)

{

sem_wait(&in);//修改

counter++;

printf(“%d\n”,counter);

if(counter==30)

{

sem_post(&handout);//告升修改

return NULL;

}

sem_post(&in);//修改

return NULL;

}

void * fteacherhandout(void *b)

{

sem_wait(&handout);//修改

printf(“teacher said:hand out over\n”);

sem_post(&handin);//修改

return NULL;

}

void * studentout(void *c)

{

sem_wait(&handin);//修改

sem_wait(&out);//修改

counter–;

printf(“%d\n”,counter);

if(counter==0)

{

sem_post(&goout);//修改

return NULL;

}

sem_post(&out);//修改

}

void * fteacherout(void *d)

{

sem_wait(&goout);//修改

printf(“teacher go out”);

return NULL;

}

void main()

{

int i=0;

//–以下是修改的部分

sem_init(&in,0,1);

sem_init(&out,0,1);

sem_init(&handin,0,0);

sem_init(&handout,0,0);

sem_init(&goout,0,0);

//

pthread_t thread1,thread2,teacher1,teacher2;

pthread_attr_t attr;

pthread_attr_init(&attr);

for(i=0;i

{

pthread_create(&thread1,&attr,studentIn,NULL);

}

for(i=0;i

{

pthread_create(&thread2,&attr,studentout,NULL);

}

pthread_create(&teacher1,&attr,fteacherhandout,NULL);

pthread_create(&teacher2,&attr,fteacherout,NULL);

return;

Linux多进程和线程同步的几种方式

Linux 线程同步的橘蚂笑三种方法

线程的更大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点。linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量和信号量。

一、互斥锁(mutex)

通过锁机制实现线程间的同步。

初始化锁。在Linux下,线程的互斥量数据类型是pthread_mutex_t。在使用前,要对它进行初始化。

静态分配:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

动态分配:int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr);

加锁。对共享资源的访问,要对互斥量进行加锁,如果互斥量已经上了锁,调用线程会阻塞,直到互斥量被解锁。

int pthread_mutex_lock(pthread_mutex *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

解锁。在完成了对共享资源的访问后,要对互斥量进行解锁。

int pthread_mutex_unlock(pthread_mutex_t *mutex);

销毁锁。锁在是使用完成后,需要进行销毁以释放资源。

int pthread_mutex_destroy(pthread_mutex *mutex);

view plain copy

#include

#include

#include

#include

#include “iostream”

using namespace std;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int tmp;

void* thread(void *arg)

{

cout

#include

#include “stdlib.h”

#include “unistd.h”

pthread_mutex_t mutex;

pthread_cond_t cond;

void hander(void *arg)

{

free(arg);

(void)pthread_mutex_unlock(&mutex);

}

void *thread1(void *arg)

{

pthread_cleanup_push(hander, &mutex);

while(1)

{

printf(“thread1 is running\n”);

pthread_mutex_lock(&mutex);

pthread_cond_wait(&cond, &mutex);

printf(“thread1 applied the condition\n”);

pthread_mutex_unlock(&mutex);

sleep(4);

}

pthread_cleanup_pop(0);

}

void *thread2(void *arg)

{

while(1)

{

printf(“thread2 is running\n”);

pthread_mutex_lock(&mutex);

pthread_cond_wait(&cond, &mutex);

printf(“thread2 applied the condition\n”);

pthread_mutex_unlock(&mutex);

sleep(1);

}

}

int main()

{

pthread_t thid1,thid2;

printf(“condition variable study!\n”);

pthread_mutex_init(&mutex, NULL);

pthread_cond_init(&cond, NULL);

pthread_create(&thid1, NULL, thread1, NULL);

pthread_create(&thid2, NULL, thread2, NULL);

sleep(1);

do

{

pthread_cond_signal(&cond);

}while(1);

sleep(20);

pthread_exit(0);

return 0;

}

view plain copy

#include

#include

#include “stdio.h”

#include “stdlib.h”

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

struct node

{

int n_number;

struct node *n_next;

}*head = NULL;

static void cleanup_handler(void *arg)

{

printf(“Cleanup handler of second thread./n”);

free(arg);

(void)pthread_mutex_unlock(&mtx);

}

static void *thread_func(void *arg)

{

struct node *p = NULL;

pthread_cleanup_push(cleanup_handler, p);

while (1)

{

//这个mutex主要是用来保证pthread_cond_wait的并发性

pthread_mutex_lock(&mtx);

while (head == NULL)

{

//这个while要特别说明一下,单个pthread_cond_wait功能很完善,为何

//这里要有一个while (head == NULL)呢?因为pthread_cond_wait里的线

//程可能会被意外唤醒,如果这个时候head != NULL,则不是我们想要的情况。

//这个时候,应该让线程继续进入pthread_cond_wait

// pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,

//然后阻塞在等待对列里休眠,直到再次被唤醒(大多数情况下是等待的条件成立

//而被唤醒,唤醒后,该进程会先锁定先pthread_mutex_lock(&mtx);,再读取资源

//用这个流程是比较清楚的

pthread_cond_wait(&cond, &mtx);

p = head;

head = head->n_next;

printf(“Got %d from front of queue/n”, p->n_number);

free(p);

}

pthread_mutex_unlock(&mtx); //临界区数据操作完毕,释放互斥锁

}

pthread_cleanup_pop(0);

return 0;

}

int main(void)

{

pthread_t tid;

int i;

struct node *p;

//子线程会一直等待资源,类似生产者和消费者,但是这里的消费者可以是多个消费者,而

//不仅仅支持普通的单个消费者,这个模型虽然简单,但是很强大

pthread_create(&tid, NULL, thread_func, NULL);

sleep(1);

for (i = 0; i n_number = i;

pthread_mutex_lock(&mtx); //需要操作head这个临界资源,先加锁,

p->n_next = head;

head = p;

pthread_cond_signal(&cond);

pthread_mutex_unlock(&mtx); //解锁

sleep(1);

}

printf(“thread 1 wanna end the line.So cancel thread 2./n”);

//关于pthread_cancel,有一点额外的说明,它是从外部终止子线程,子线程会在最近的取消点,退出

//线程,而在我们的代码里,最近的取消点肯定就是pthread_cond_wait()了。

pthread_cancel(tid);

pthread_join(tid, NULL);

printf(“All done — exiting/n”);

return 0;

}

三、信号量(sem)

如同进程一样,线程也可以通过信号量来实现通信,虽然是轻量级的。信号量函数的名字都以”sem_”打头。线程使用的基本信号量函数有四个。

信号量初始化。

int sem_init (sem_t *sem , int pshared, unsigned int value);

这是对由sem指定的信号量进行初始化,设置好它的共享选项(linux 只支持为0,即表示它是当前进程的局部信号量),然后给它一个初始值VALUE。

等待信号量。给信号量减1,然后等待直到信号量的值大于0。

int sem_wait(sem_t *sem);

释放信号量。信号量值加1。并通知其他等待线程。

int sem_post(sem_t *sem);

销毁信号量。我们用完信号量后都它进行清理。归还占有的一切资源。

int sem_destroy(sem_t *sem);

view plain copy

#include

#include

#include

#include

#include

#include

#define return_if_fail(p) if((p) == 0){printf (“:func error!/n”, __func__);return;}

typedef struct _PrivInfo

{

sem_t s1;

sem_t s2;

time_t end_time;

}PrivInfo;

static void info_init (PrivInfo* thiz);

static void info_destroy (PrivInfo* thiz);

static void* pthread_func_1 (PrivInfo* thiz);

static void* pthread_func_2 (PrivInfo* thiz);

int main (int argc, char** argv)

{

pthread_t pt_1 = 0;

pthread_t pt_2 = 0;

int ret = 0;

PrivInfo* thiz = NULL;

thiz = (PrivInfo* )malloc (sizeof (PrivInfo));

if (thiz == NULL)

{

printf (“: Failed to malloc priv./n”);

return -1;

}

info_init (thiz);

ret = pthread_create (&pt_1, NULL, (void*)pthread_func_1, thiz);

if (ret != 0)

{

perror (“pthread_1_create:”);

}

ret = pthread_create (&pt_2, NULL, (void*)pthread_func_2, thiz);

if (ret != 0)

{

perror (“pthread_2_create:”);

}

pthread_join (pt_1, NULL);

pthread_join (pt_2, NULL);

info_destroy (thiz);

return 0;

}

static void info_init (PrivInfo* thiz)

{

return_if_fail (thiz != NULL);

thiz->end_time = time(NULL) + 10;

sem_init (&thiz->s1, 0, 1);

sem_init (&thiz->s2, 0, 0);

return;

}

static void info_destroy (PrivInfo* thiz)

{

return_if_fail (thiz != NULL);

sem_destroy (&thiz->s1);

sem_destroy (&thiz->s2);

free (thiz);

thiz = NULL;

return;

}

static void* pthread_func_1 (PrivInfo* thiz)

{

return_if_fail(thiz != NULL);

while (time(NULL) end_time)

{

sem_wait (&thiz->s2);

printf (“pthread1: pthread1 get the lock./n”);

sem_post (&thiz->s1);

printf (“pthread1: pthread1 unlock/n”);

sleep (1);

}

return;

}

static void* pthread_func_2 (PrivInfo* thiz)

{

return_if_fail (thiz != NULL);

while (time (NULL) end_time)

{

sem_wait (&thiz->s1);

printf (“pthread2: pthread2 get the unlock./n”);

sem_post (&thiz->s2);

printf (“pthread2: pthread2 unlock./n”);

sleep (1);

}

return;

}

返回列表

上一篇:kalilinux用adb刷机

linux sem wait的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux sem wait,Linux下的sem_wait等待函数简介,linux 信号量问题 编译错误 好像不识别sem_t定义的变量,Linux多进程和线程同步的几种方式的信息别忘了在本站进行查找喔。


数据运维技术 » Linux下的sem_wait等待函数简介 (linux sem wait)