重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

信号量函数用c语言怎么写 C语言信号

信号量函数用法

生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

创新互联建站专注于石嘴山企业网站建设,自适应网站建设,电子商务商城网站建设。石嘴山网站建设公司,为石嘴山等地区提供建站服务。全流程定制网站,专业设计,全程项目跟踪,创新互联建站专业和态度为您提供的服务

#include windows.h

#include iostream

const unsigned short SIZE_OF_BUFFER = 10; //缓冲区长度

unsigned short ProductID = 0; //产品号

unsigned short ConsumeID = 0; //将被消耗的产品号

unsigned short in = 0; //产品进缓冲区时的缓冲区下标

unsigned short out = 0; //产品出缓冲区时的缓冲区下标

int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列

bool g_continue = true; //控制程序结束

HANDLE g_hMutex; //用于线程间的互斥

HANDLE g_hFullSemaphore; //当缓冲区满时迫使生产者等待

HANDLE g_hEmptySemaphore; //当缓冲区空时迫使消费者等待

DWORD WINAPI Producer(LPVOID); //生产者线程

DWORD WINAPI Consumer(LPVOID); //消费者线程

int main()

{

//创建各个互斥信号

g_hMutex = CreateMutex(NULL,FALSE,NULL);

g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL);

g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);

//调整下面的数值,可以发现,当生产者个数多于消费者个数时,

//生产速度快,生产者经常等待消费者;反之,消费者经常等待

const unsigned short PRODUCERS_COUNT = 3; //生产者的个数

const unsigned short CONSUMERS_COUNT = 1; //消费者的个数

//总的线程数

const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;

HANDLE hThreads[PRODUCERS_COUNT]; //各线程的handle

DWORD producerID[CONSUMERS_COUNT]; //生产者线程的标识符

DWORD consumerID[THREADS_COUNT]; //消费者线程的标识符

//创建生产者线程

for (int i=0;iPRODUCERS_COUNT;++i){

hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,producerID[i]);

if (hThreads[i]==NULL) return -1;

}

//创建消费者线程

for (int i=0;iCONSUMERS_COUNT;++i){

hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,consumerID[i]);

if (hThreads[i]==NULL) return -1;

}

while(g_continue){

if(getchar()){ //按回车后终止程序运行

g_continue = false;

}

}

return 0;

}

//生产一个产品。简单模拟了一下,仅输出新产品的ID号

void Produce()

{

std::cerr "Producing " ++ProductID " ... ";

std::cerr "Succeed" std::endl;

}

//把新生产的产品放入缓冲区

void Append()

{

std::cerr "Appending a product ... ";

g_buffer[in] = ProductID;

in = (in+1)%SIZE_OF_BUFFER;

std::cerr "Succeed" std::endl;

//输出缓冲区当前的状态

for (int i=0;iSIZE_OF_BUFFER;++i){

std::cout i ": " g_buffer[i];

if (i==in) std::cout " -- 生产";

if (i==out) std::cout " -- 消费";

std::cout std::endl;

}

}

//从缓冲区中取出一个产品

void Take()

{

std::cerr "Taking a product ... ";

ConsumeID = g_buffer[out];

out = (out+1)%SIZE_OF_BUFFER;

std::cerr "Succeed" std::endl;

//输出缓冲区当前的状态

for (int i=0;iSIZE_OF_BUFFER;++i){

std::cout i ": " g_buffer[i];

if (i==in) std::cout " -- 生产";

if (i==out) std::cout " -- 消费";

std::cout std::endl;

}

}

//消耗一个产品

void Consume()

{

std::cerr "Consuming " ConsumeID " ... ";

std::cerr "Succeed" std::endl;

}

//生产者

DWORD WINAPI Producer(LPVOID lpPara)

{

while(g_continue){

WaitForSingleObject(g_hFullSemaphore,INFINITE);

WaitForSingleObject(g_hMutex,INFINITE);

Produce();

Append();

Sleep(1500);

ReleaseMutex(g_hMutex);

ReleaseSemaphore(g_hEmptySemaphore,1,NULL);

}

return 0;

}

//消费者

DWORD WINAPI Consumer(LPVOID lpPara)

{

while(g_continue){

WaitForSingleObject(g_hEmptySemaphore,INFINITE);

WaitForSingleObject(g_hMutex,INFINITE);

Take();

Consume();

Sleep(1500);

ReleaseMutex(g_hMutex);

ReleaseSemaphore(g_hFullSemaphore,1,NULL);

}

return 0;

如何用C语言实现P,V两个程序,使信号量只加不减或只减不加

是什么样的程序我不清楚。

不过你可以定义一个 bool变量当开关嘛, 比如p操作时为 true,v操作时为false, 这样就可以分开两个操作了

C语言 信号量的疑惑。。

一个是Posix实现,一个是System V实现

使用的环境不一样

一般来讲SV的适用于进程同步,POSIX适用于线程同步

System V进程同步 api:semget/semop/semctl

POSIX 线程同步 api:sem_init/sem_destroy

不过POSIX貌似还会分为有名和无名信号量上面说的是无名信号量。

具体的还要看使用的环境。

c语言实例,linux线程同步的信号量方式 谢谢

这么高的悬赏,实例放后面。信号量(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);

#include stdlib.h  

#include stdio.h  

#include unistd.h  

#include pthread.h  

#include semaphore.h  

#include errno.h  

#define return_if_fail(p) if((p) == 0){printf ("[%s]: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 ("[%s]: 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)  thiz-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)  thiz-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;  

}

用c语言或c++编写编程实现生产者消费者或读写者的同步问题

实现一个队列CQueue

CQueue提供两个公有成员函数

addTail():往队列尾部增加一个元素

removeHead():读出并移除队列的第一个元素

生产者:两个线程通过调用CQueue::addTail()往队列中增加元素

消费者:一个线程通过调用CQueue::removeHead()从队列中读取元素

#include iostream

#include list

#include windows.h

#include process.h

using namespace std;

#define P(sem) WaitForSingleObject(sem,INFINITE)

#define V(sem) ReleaseSemaphore(sem,1,NULL)

class CQueue

{

public:

void addTail();//往队列尾部增加一个元素

void removeHead();//读出并移除队列的第一个元素

private:

listint L;

};

CQueue buffer;//全局的缓冲区

const int buf_size = 10;//缓冲区大小

static int GOODS_ID = 0;//商品序号

const int producers = 3;//生产者数量

const int consumers = 8;//消费者数量

void ProducerThread(void* param);

void ConsumerThread(void* param);

HANDLE empty,occupy,op_mutex;

int main()

{

int i;

int p_id[producers],c_id[consumers];

occupy = CreateSemaphore(NULL,0,buf_size,NULL);//占用位置

empty = CreateSemaphore(NULL,buf_size,buf_size,NULL);//空余位置

op_mutex = CreateSemaphore(NULL,1,1,NULL);//操作互斥量

for(i=0;iproducers;++i)

{

p_id[i] = i+1;

_beginthread(ProducerThread,0,p_id+i);

}

for(i=0;iconsumers;++i)

{

c_id[i] = i+1;

_beginthread(ConsumerThread,0,c_id+i);

}

while(getchar()=='\n') break;

return 0;

}

void CQueue::addTail()

{

L.insert(L.end(),++GOODS_ID);

}

void CQueue::removeHead()

{

cout*L.begin()endl;

L.erase(L.begin());

}

void ProducerThread(void* param)

{

int id = *(int*)param;

while(1)

{

P(empty);

P(op_mutex);

Sleep(100);

buffer.addTail();

printf("Producer_%d produced %d\n",id,GOODS_ID);

V(op_mutex);

V(occupy);

}

}

void ConsumerThread(void* param)

{

int id = *(int*)param;

while(1)

{

P(occupy);

P(op_mutex);

Sleep(100);

printf("Consumer_%d consumed ",id);

buffer.removeHead();

V(op_mutex);

V(empty);

}

}

请教一个Linux下C语言的进程间的信号问题

linux中的进程通信分为三个部分:低级通信,管道通信和进程间通信IPC(inter process communication)。linux的低级通信主要用来传递进程的控制信号——文件锁和软中断信号机制。linux的进程间通信IPC有三个部分——①信号量,②共享内存和③消息队列。以下是我编写的linux进程通信的C语言实现代码。操作系统为redhat9.0,编辑器为vi,编译器采用gcc。下面所有实现代码均已经通过测试,运行无误。

一.低级通信--信号通信

signal.c

#include

#include

#include

/*捕捉到信号sig之后,执行预先预定的动作函数*/

void sig_alarm(int sig)

{

printf("---the signal received is %d. /n", sig);

signal(SIGINT, SIG_DFL); //SIGINT终端中断信号,SIG_DFL:恢复默认行为,SIN_IGN:忽略信号

}

int main()

{

signal(SIGINT, sig_alarm);//捕捉终端中断信号

while(1)

{

printf("waiting here!/n");

sleep(1);

}

return 0;

}

二.管道通信

pipe.c

#include

#define BUFFER_SIZE 30

int main()

{

int x;

int fd[2];

char buf[BUFFER_SIZE];

char s[BUFFER_SIZE];

pipe(fd);//创建管道

while((x=fork())==-1);//创建管道失败时,进入循环

/*进入子进程,子进程向管道中写入一个字符串*/

if(x==0)

{

sprintf(buf,"This is an example of pipe!/n");

write(fd[1],buf,BUFFER_SIZE);

exit(0);

}

/*进入父进程,父进程从管道的另一端读出刚才写入的字符串*/

else

{

wait(0);//等待子进程结束

read(fd[0],s,BUFFER_SIZE);//读出字符串,并将其储存在char s[]中

printf("%s",s);//打印字符串

}

return 0;

}

三.进程间通信——IPC

①信号量通信

sem.c

#include

#include

#include

#include types.h

#include ipc.h

#include sem.h

/*联合体变量*/

union semun

{

int val; //信号量初始值

struct semid_ds *buf;

unsigned short int *array;

struct seminfo *__buf;

};

/*函数声明,信号量定义*/

static int set_semvalue(void); //设置信号量

static void del_semvalue(void);//删除信号量

static int semaphore_p(void); //执行P操作

static int semaphore_v(void); //执行V操作

static int sem_id; //信号量标识符

int main(int argc, char *argv[])

{

int i;

int pause_time;

char op_char = 'O';

srand((unsigned int)getpid());

sem_id = semget((key_t)1234, 1, 0666 | IPC_CREAT);//创建一个信号量,IPC_CREAT表示创建一个新的信号量

/*如果有参数,设置信号量,修改字符*/

if (argc 1)

{

if (!set_semvalue())

{

fprintf(stderr, "Failed to initialize semaphore/n");

exit(EXIT_FAILURE);

}

op_char = 'X';

sleep(5);

}

for(i = 0; i 10; i++)

{

/*执行P操作*/

if (!semaphore_p())

exit(EXIT_FAILURE);

printf("%c", op_char);

fflush(stdout);

pause_time = rand() % 3;

sleep(pause_time);

printf("%c", op_char);

fflush(stdout);

/*执行V操作*/

if (!semaphore_v())

exit(EXIT_FAILURE);

pause_time = rand() % 2;

sleep(pause_time);

}

printf("/n%d - finished/n", getpid());

if (argc 1)

{

sleep(10);

del_semvalue(); //删除信号量

}

exit(EXIT_SUCCESS);

}

/*设置信号量*/

static int set_semvalue(void)

{

union semun sem_union;

sem_union.val = 1;

if (semctl(sem_id, 0, SETVAL, sem_union) == -1)

return(0);

return(1);

}

/*删除信号量*/

static void del_semvalue(void)

{

union semun sem_union;

if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)

fprintf(stderr, "Failed to delete semaphore/n");

}

/*执行P操作*/

static int semaphore_p(void)

{

struct sembuf sem_b;

sem_b.sem_num = 0;

sem_b.sem_op = -1; /* P() */

sem_b.sem_flg = SEM_UNDO;

if (semop(sem_id, sem_b, 1) == -1)

{

fprintf(stderr, "semaphore_p failed/n");

return(0);

}

return(1);

}

/*执行V操作*/

static int semaphore_v(void)

{

struct sembuf sem_b;

sem_b.sem_num = 0;

sem_b.sem_op = 1; /* V() */

sem_b.sem_flg = SEM_UNDO;

if (semop(sem_id, sem_b, 1) == -1)

{

fprintf(stderr, "semaphore_v failed/n");

return(0);

}

return(1);

}

②消息队列通信

send.c

#include

#include

#include

#include

#include

#include types.h

#include ipc.h

#include msg.h

#define MAX_TEXT 512

/*用于消息收发的结构体--my_msg_type:消息类型,some_text:消息正文*/

struct my_msg_st

{

long int my_msg_type;

char some_text[MAX_TEXT];

};

int main()

{

int running = 1;//程序运行标识符

struct my_msg_st some_data;

int msgid;//消息队列标识符

char buffer[BUFSIZ];

/*创建与接受者相同的消息队列*/

msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

if (msgid == -1)

{

fprintf(stderr, "msgget failed with error: %d/n", errno);

exit(EXIT_FAILURE);

}

/*向消息队列中发送消息*/

while(running)

{

printf("Enter some text: ");

fgets(buffer, BUFSIZ, stdin);

some_data.my_msg_type = 1;

strcpy(some_data.some_text, buffer);

if (msgsnd(msgid, (void *)some_data, MAX_TEXT, 0) == -1)

{

fprintf(stderr, "msgsnd failed/n");

exit(EXIT_FAILURE);

}

if (strncmp(buffer, "end", 3) == 0)

{

running = 0;

}

}

exit(EXIT_SUCCESS);

}

receive.c

#include

#include

#include

#include

#include

#include types.h

#include ipc.h

#include msg.h

/*用于消息收发的结构体--my_msg_type:消息类型,some_text:消息正文*/

struct my_msg_st

{

long int my_msg_type;

char some_text[BUFSIZ];

};

int main()

{

int running = 1;//程序运行标识符

int msgid; //消息队列标识符

struct my_msg_st some_data;

long int msg_to_receive = 0;//接收消息的类型--0表示msgid队列上的第一个消息

/*创建消息队列*/

msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

if (msgid == -1)

{

fprintf(stderr, "msgget failed with error: %d/n", errno);

exit(EXIT_FAILURE);

}

/*接收消息*/

while(running)

{

if (msgrcv(msgid, (void *)some_data, BUFSIZ,msg_to_receive, 0) == -1)

{

fprintf(stderr, "msgrcv failed with error: %d/n", errno);

exit(EXIT_FAILURE);

}

printf("You wrote: %s", some_data.some_text);

if (strncmp(some_data.some_text, "end", 3) == 0)

{

running = 0;

}

}

/*删除消息队列*/

if (msgctl(msgid, IPC_RMID, 0) == -1)

{

fprintf(stderr, "msgctl(IPC_RMID) failed/n");

exit(EXIT_FAILURE);

}

exit(EXIT_SUCCESS);

}

③共享内存通信

share.h

#define TEXT_SZ 2048 //申请共享内存大小

struct shared_use_st

{

int written_by_you; //written_by_you为1时表示有数据写入,为0时表示数据已经被消费者提走

char some_text[TEXT_SZ];

};

producer.c

#include

#include

#include

#include

#include types.h

#include ipc.h

#include shm.h

#include "share.h"

int main()

{

int running = 1; //程序运行标志位

void *shared_memory = (void *)0;

struct shared_use_st *shared_stuff;

char buffer[BUFSIZ];

int shmid; //共享内存标识符

/*创建共享内存*/

shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);

if (shmid == -1)

{

fprintf(stderr, "shmget failed/n");

exit(EXIT_FAILURE);

}

/*将共享内存连接到一个进程的地址空间中*/

shared_memory = shmat(shmid, (void *)0, 0);//指向共享内存第一个字节的指针

if (shared_memory == (void *)-1)

{

fprintf(stderr, "shmat failed/n");

exit(EXIT_FAILURE);

}

printf("Memory attached at %X/n", (int)shared_memory);

shared_stuff = (struct shared_use_st *)shared_memory;

/*生产者写入数据*/

while(running)

{

while(shared_stuff-written_by_you == 1)

{

sleep(1);

printf("waiting for client.../n");

}

printf("Enter some text: ");

fgets(buffer, BUFSIZ, stdin);

strncpy(shared_stuff-some_text, buffer, TEXT_SZ);

shared_stuff-written_by_you = 1;

if (strncmp(buffer, "end", 3) == 0)

{

running = 0;

}

}

/*该函数用来将共享内存从当前进程中分离,仅使得当前进程不再能使用该共享内存*/

if (shmdt(shared_memory) == -1)

{

fprintf(stderr, "shmdt failed/n");

exit(EXIT_FAILURE);

}

printf("producer exit./n");

exit(EXIT_SUCCESS);

}

customer.c

#include

#include

#include

#include

#include types.h

#include ipc.h

#include shm.h

#include "share.h"

int main()

{

int running = 1;//程序运行标志位

void *shared_memory = (void *)0;

struct shared_use_st *shared_stuff;

int shmid; //共享内存标识符

srand((unsigned int)getpid());

/*创建共享内存*/

shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666 | IPC_CREAT);

if (shmid == -1)

{

fprintf(stderr, "shmget failed/n");

exit(EXIT_FAILURE);

}

/*将共享内存连接到一个进程的地址空间中*/

shared_memory = shmat(shmid, (void *)0, 0);//指向共享内存第一个字节的指针

if (shared_memory == (void *)-1)

{

fprintf(stderr, "shmat failed/n");

exit(EXIT_FAILURE);

}

printf("Memory attached at %X/n", (int)shared_memory);

shared_stuff = (struct shared_use_st *)shared_memory;

shared_stuff-written_by_you = 0;

/*消费者读取数据*/

while(running)

{

if (shared_stuff-written_by_you)

{

printf("You wrote: %s", shared_stuff-some_text);

sleep( rand() % 4 );

shared_stuff-written_by_you = 0;

if (strncmp(shared_stuff-some_text, "end", 3) == 0)

{

running = 0;

}

}

}

/*该函数用来将共享内存从当前进程中分离,仅使得当前进程不再能使用该共享内存*/

if (shmdt(shared_memory) == -1)

{

fprintf(stderr, "shmdt failed/n");

exit(EXIT_FAILURE);

}

/*将共享内存删除,所有进程均不能再访问该共享内存*/

if (shmctl(shmid, IPC_RMID, 0) == -1)

{

fprintf(stderr, "shmctl(IPC_RMID) failed/n");

exit(EXIT_FAILURE);

}

exit(EXIT_SUCCESS);

}

摘自:


名称栏目:信号量函数用c语言怎么写 C语言信号
转载注明:http://cqcxhl.cn/article/docpggo.html

其他资讯

在线咨询
服务热线
服务热线:028-86922220
TOP