程序功能:
程序分成兩個部分,一個寫端一個讀端,採用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;
}