程序功能:
程序分成两个部分,一个写端一个读端,采用fifo进行进程间的通信,写端负责写入命令,读端负责读命令,读端采用多线程的方式进行编写程序,创建两个线程,一个唤醒线程用于唤醒发送线程,一个发送线程用于发送消息;主线程读取命令后,将命令添加到任务队列中,唤醒线程进行判断,如果任务队列为空则睡眠,否则唤醒发送线程,采用条件变量与互斥锁进行线程间的同步互斥;
程序如下:
(1)、pthread_read.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <fcntl.h>
struct node
{
int cmd;
struct node *next;
};
struct node *head;
char buf[100];
pthread_mutex_t send_mutex, wake_mutex;
pthread_cond_t send_cond, wake_cond;
struct node *create_list(void);
void insert_list(struct node *, int );
void delete_list(struct node *, int );
int is_empty_list(struct node *);
int get_list_cmd(struct node *);
void *wake_func(void *);
void *send_func(void *);
int main(int argc, const char *argv[])
{
pthread_t wake_pthread, send_pthread;
int err;
int fifo_fd;
char cmd_buf[20];
if (argc < 2)
{
fprintf(stderr, "usages: %s filename\n", argv[0]);
exit(-1);
}
head = create_list();
if ((fifo_fd = open(argv[1], O_RDONLY)) < 0)
{
perror("failed to open fifo");
exit(-1);
}
err = pthread_create(&wake_pthread, NULL, wake_func, NULL);
if (err < 0)
{
perror("failed to create wake_pthread");
exit(-1);
}
err = pthread_create(&send_pthread, NULL, send_func, NULL);
if (err < 0)
{
perror("failed to create send_pthread");
exit(-1);
}
err = pthread_mutex_init(&wake_mutex, NULL);
if (err < 0)
{
perror("failed to init wake_mutex");
exit(-1);
}
err = pthread_mutex_init(&send_mutex, NULL);
if (err < 0)
{
perror("failed to init send_mutex");
exit(-1);
}
err = pthread_cond_init(&wake_cond, NULL);
if (err < 0)
{
perror("failed to init wake_cond");
exit(-1);
}
err = pthread_cond_init(&send_cond, NULL);
if (err < 0)
{
perror("failed to init send_cond");
exit(-1);
}
while(1)
{
read(fifo_fd, cmd_buf, sizeof(cmd_buf));
if(strncmp(cmd_buf, "quit", 4) == 0)
break;
insert_list(head, atoi(cmd_buf));
pthread_mutex_lock(&wake_mutex);
pthread_cond_signal(&wake_cond);
pthread_mutex_unlock(&wake_mutex);
}
return 0;
}
struct node *create_list(void)
{
struct node *head;
head = (struct node *)malloc(sizeof(struct node));
head->next = NULL;
return head;
}
void insert_list(struct node *head, int cmd)
{
struct node *new;
new = (struct node *)malloc(sizeof(struct node));
new->cmd = cmd;
new->next = head->next;
head->next = new;
return ;
}
void delete_list(struct node *head, int cmd)
{
struct node *p = head->next;
struct node *q = head;
while (p != NULL)
{
if (p->cmd == cmd)
break;
p = p->next;
q = q->next;
}
q->next = p->next;
p->next = NULL;
free(p);
return ;
}
int is_empty_list(struct node *head)
{
int value;
if (head->next == NULL)
value = 1;
else
value = 0;
return value;
}
int get_list_cmd(struct node *head)
{
struct node *p = head->next;
return p->cmd;
}
void *wake_func(void *arg)
{
int cmd;
while (1)
{
pthread_mutex_lock(&wake_mutex);
if (is_empty_list(head))
pthread_cond_wait(&wake_cond, &wake_mutex);
cmd = get_list_cmd(head);
printf("cmd : %d\n", cmd);
switch(cmd)
{
case 1:
strcpy(buf, "fire is coming");
pthread_cond_signal(&send_cond);
delete_list(head, cmd);
break;
case 2:
strcpy(buf, "thief is coming");
pthread_cond_signal(&send_cond);
delete_list(head, cmd);
break;
case 3:
strcpy(buf, "take photos");
pthread_cond_signal(&send_cond);
delete_list(head, cmd);
break;
default:
delete_list(head, cmd);
break;
}
pthread_mutex_unlock(&wake_mutex);
}
return ;
}
void *send_func(void *arg)
{
while(1)
{
pthread_mutex_lock(&send_mutex);
pthread_cond_wait(&send_cond, &send_mutex);
pthread_mutex_unlock(&send_mutex);
printf("recv: %s\n", buf);
}
return ;
}
(2)write_fifo.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, const char *argv[])
{
int fifo_fd;
char buf[20];
if (argc < 2)
{
fprintf(stderr, "usages: %s fifo\n", argv[0]);
exit(-1);
}
if (mkfifo(argv[1], 0666 | O_CREAT | O_EXCL) < 0)
{
if (errno == EEXIST)
{
if (mkfifo(argv[1], 0666) < 0)
{
perror("failed to create fifo");
exit(-1);
}
}
}
if ((fifo_fd = open(argv[1], O_WRONLY)) < 0)
{
perror("failed to open fifo");
exit(-1);
}
while(1)
{
printf(">");
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf) - 1] = 0;
write(fifo_fd, buf, strlen(buf) + 1);
if(strncmp(buf, "quit", 4) == 0)
break;
}
return 0;
}