[TOC]
// + 补全生产者、计算者、消费者程序
// - 完成函数 buffer_init
// - 完成函数 buffer_get
// - 完成函数 buffer_put
// - 补全函数 main
// * 创建生产者、计算者、消费者
//
// + 程序最终输出
// - 生产者输出 a b c d e f g h
// - 消费者输出 A B C D E F G H
// - 消费者输出 A B C D E F G H
// - 两者交叉输出
//
// + 不准对函数 produce 、函数 compute、 函数 consume 进行任何改动
// - 如果改动,则该题没有分数
//
// + 本题对 buffer 进行了抽象和封装
// - buffer_pc 连接 producer 和 computer
// - buffer_cc 连接 computer 和 consumer
#include <stdio.h>
#include <pthread.h>
#include <ctype.h>
#define CAPACITY 4 // 缓冲区的最大容量
struct buffer {
int data[CAPACITY];
int in; // 缓冲区的写指针
int out; // 缓冲区的读指针
pthread_mutex_t mutex;
pthread_cond_t wait_empty_buffer;
pthread_cond_t wait_full_buffer;
};
// 初始化 buffer,需要初始化用于同步的字段
void buffer_init(struct buffer *buffer)
{
buffer->in = 0;
buffer->out = 0;
}
// 判断缓冲区是否为空
int buffer_is_empty(struct buffer *buffer)
{
return buffer->in == buffer->out;
}
// 判断缓冲区是否为满
int buffer_is_full(struct buffer *buffer)
{
return (buffer->in + 1) % CAPACITY == buffer->out;
}
// 向缓冲区中追加一个数据,如果缓冲区为满,则等待
void buffer_put(struct buffer *buffer, int item)
{
}
// 从缓冲区中取走一个数据,如果缓冲区为空,则等待
int buffer_get(struct buffer *buffer)
{
}
#define ITEM_COUNT (2 * CAPACITY)
struct buffer buffer_pc, buffer_cc;
void *produce(void *arg)
{
int i;
int item;
for (i = 0; i < ITEM_COUNT; i++) {
item = 'a' + i;
printf("produce item: %c\n", item);
buffer_put(&buffer_pc, item);
}
return NULL;
}
void *compute(void *arg)
{
int i;
int item;
for (i = 0; i < ITEM_COUNT; i++) {
item = buffer_get(&buffer_pc);
item = toupper(item);
printf(" compute item: %c\n", item);
buffer_put(&buffer_cc, item);
}
return NULL;
}
void *consume(void *arg)
{
int i;
int item;
for (i = 0; i < ITEM_COUNT; i++) {
item = buffer_get(&buffer_cc);
printf(" consume item: %c\n", item);
}
return NULL;
}
int main()
{
buffer_init(&buffer_pc);
buffer_init(&buffer_cc);
pthread_t producer_tid;
pthread_t computer_tid;
pthread_t consumer_tid;
pthread_create(&producer_tid, NULL, produce, NULL);
pthread_create(&computer_tid, NULL, compute, NULL);
pthread_create(&consumer_tid, NULL, consume, NULL);
pthread_join(consumer_tid,NULL);
return 0;
}
// 实现命令 mygrep string file
// + 该命令逐行读取文件,如果行包括目标字符串,则打印该行
// + 该命令有两个命令行参数
// - 参数 string,要搜索的字符串
// - 参数 file,要查找的文件名
//
// 例子,在文件 /etc/passwd 中查找字符串 root,打印包含该字符串的行
// $ ./mygrep root /etc/passwd
// root:x:0:0:root:/root:/bin/bash
//
// 提示,可以使用函数 strstr 在字符串中查找字符串
// https://www.runoob.com/cprogramming/c-function-strstr.html
// + 实现函数 list_visit
// - 主程序遍历链表 list 的每个节点
// - 对每个节点创建一个子线程,在这道题目中,总共创建 7 个子线程
// - 在每个子线程中,打印 node->data
//
// + 实现函数 wait_sub_threads
// - 等待所有的子线程执行完毕
// - 在 list_visit 时,需要记录下所有线程的 ID,记录在全局变量中
// - 在 wait_sub_threads 中使用 pthread_join
//
// + 程序可能的输出结果
// - 字符 a b c d e f g 每个出现一次,出现的顺序可能是随机的
// - END 一定是最后出现
// a
// d
// b
// e
// c
// f
// g
// END
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
struct node {
char data;
struct node *next;
};
pthread_t workers[7];
struct node *node_create(char data)
{
struct node *node = malloc(sizeof(struct node));
node->data = data;
node->next = NULL;
return node;
}
void list_visit(struct node *list)
{
}
// 遍历算法,供参考
void list_print(struct node *list)
{
struct node *node = list;
while (node) {
printf("%c\n", node->data);
node = node->next;
}
}
void wait_sub_threads()
{
}
int main()
{
struct node *list = NULL;
for (char data = 'g'; data >= 'a'; data--) {
struct node *node = node_create(data);
node->next = list;
list = node;
}
list_print(list);
wait_sub_threads();
puts("END");
return 0;
}
// 通过 fork/exec/pipe/dup 实现 cat </etc/passwd | wc -l >result.txt
//
// + 父进程创建子进程
// - 在父进程中实现功能 cat </etc/passwd
// - 在子进程中实现功能 wc -l >result.txt
// - 不能实现为
// * 在子进程中实现功能 cat </etc/passwd
// * 在父进程中实现功能 wc -l >result.txt
//
// + 该题不要求实现一个通用的 shell 程序
// - 不需要使用 strtok 对字符串进行分割处理
// - 假设字符串已经分割处理好了
// * 父进程,使用 execlp("cat") 执行命令,使用 open("/etc/passwd") 打开文件
// * 子进程,使用 execlp("wc") 执行命令,使用 open("result.txt") 打开文件
//
// + 请严格按要求完成
// - 把作业 sh3.c 的内容复制过来,是没有分数的