
正文
c语言信号量函数 信号量操作函数
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
Linux:睡眠理发师问题(用C语言实现)
/*基于信号量采用多线程技术实现进程同步*/
#include pthread.h
#include stdio.h
#include unistd.h
#include stdlib.h
#include semaphore.h
#include sys/time.h
#include math.h
#define CHAIRS 5 //椅子数
sem_t customers; //等待服务的顾客信号量
sem_t barbers; //等待顾客的理发师信号量
pthread_mutex_t mutex; //互斥变量
int waiting = 0; //正在等待的顾客数
void *barber(void *arg);
void *customer(void *num);
void cut_hair(void);
double timediff(struct timeval i,struct timeval j);
void seed_random(void);
double flat(void);
double normal(void);
double bursty(void);
int main()
{
int i;
seed_random();
pthread_t barber_t,customer_t;
int error;
error=pthread_create(barber_t,NULL,barber,NULL);//创建理发师线程
if(error!=0) {
printf("pthread_create is not created.../n");
return -1;
}
while(1) {
usleep(30000);//等待时间如果小于理发师理发时间则会出现等待者过多,否则不会出现等待者过多的现象
error=pthread_create(customer_t,NULL,customer,NULL);//创建顾客线程
if(error!=0) {
printf("pthread_create is not created.../n");
return -1;
}
}
}
double timediff(struct timeval now,struct timeval earlier)
{
if(now.tv_sec == earlier.tv_sec)
return (now.tv_usec - earlier.tv_usec)/1000000.0;
else
return (1000000*(now.tv_sec - earlier.tv_sec) + now.tv_usec - earlier.tv_usec)/1000000.0;
}
void *barber(void *arg)
{
while(1)
{
sem_wait(customers);//顾客信号量-1
pthread_mutex_lock(mutex);
waiting = waiting -1;
sem_post(barbers);//
pthread_mutex_unlock(mutex);
cut_hair();//理发
}
}
void cut_hair(void)
{
printf(" Barber:I am cutting the customer's hair.../n");
usleep(100000);//理发时间
printf(" Barber:done./n");
}
void *customer(void *num)
{
pthread_mutex_lock(mutex);
if(waitingCHAIRS)
{
waiting = waiting + 1;
sem_post(customers);
pthread_mutex_unlock(mutex);
sem_wait(barbers);
}
else
{
printf(" Waiter is too much.../n");
pthread_mutex_unlock(mutex);
}
//释放占用的资源
}
void seed_random(void)
{
struct timeval randtime;
unsigned short xsub1[3];
gettimeofday(randtime,(struct timezone *)0);
xsub1[0] = (ushort)randtime.tv_usec;
xsub1[1] = (ushort)(randtime.tv_usec 16);
xsub1[2] = (ushort)(getpid());
seed48(xsub1);
}
double flat()
{
return drand48()/5;
}
第二问 加个理发师忙碌数量 用来判断 即可
相关问答
Q1: 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;
}
Q2: 用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);
}
}
Q3: C语言信号量会不会溢出
会的。
在C语言中c语言信号量函数,数据的存储就像一个圆圈,正数溢出数据就会从最小负数开始,负数溢出数据同理,打个比方(简略写一下):
int
a=32768,b=-32769;
printf("a=%d,b=%d",a,b);
则会输出a=-32768,b=32767;
这样则50000输出就是(50000-32767)+(-32768)+(-1)=-15536
溢出是黑客利用操作系统的漏洞,专门开发了一种程序,加相应的参数运行后,就可以得到你电脑具有管理员资格的控制权,你在你自己电脑上能够运行的东西c语言信号量函数他可以全部做到,等于你的电脑就是他的了。溢出是程序设计者设计时的不足所带来的错误。
Q4: C语言 信号量的疑惑。。
一个是Posix实现c语言信号量函数,一个是System V实现
使用c语言信号量函数的环境不一样
一般来讲SVc语言信号量函数的适用于进程同步c语言信号量函数,POSIX适用于线程同步
System V进程同步 apic语言信号量函数:semget/semop/semctl
POSIX 线程同步 api:sem_init/sem_destroy
不过POSIX貌似还会分为有名和无名信号量上面说的是无名信号量。
具体的还要看使用的环境。
Q5: 请教一个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语言信号量函数和信号量操作函数的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。







