IO进程 寒假作业

一、请使用消息队列实现2个终端之间互相聊天

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>

void task_w()
{
	if(access("fifo1", F_OK)==-1){
		mkfifo("./fifo1", 0666);
	}

	int fd=open("./fifo1",O_WRONLY | O_TRUNC);
	
	while(1){
		char buf[128]={0};
		printf("请输入:");
		scanf("%s", buf);
		while(getchar()!=10);
		write(fd, buf, strlen(buf));
	}
	close(fd);
}

void task_r()
{
	if(access("fifo2", F_OK)==-1){
		mkfifo("./fifo2", 0666);
	}
	int fd=open("./fifo2", O_RDONLY);

	while(1){
		char buf[128]={0};
		int res=read(fd, buf, 128);
		if(res==0){break;}
		printf("\b\b\b\b\b\b\b读取到的消息为:%s\n", buf);
		printf("请输入:");
		fflush(stdout);
	}
	close(fd);
}

void handler(int signum)
{
	if(signum==SIGPIPE){
		printf("管道破裂\n");
		exit(0);
	}
}

void* thread_main(void* arg)
{
	task_r();
}

int main()
{
	signal(SIGPIPE, handler);
	pthread_t id;
	pthread_create(&id, 0, thread_main, 0);
	pthread_detach(id);
	
	task_w();
	return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>

void task_w()
{
	if(access("fifo2", F_OK)==-1){
		mkfifo("./fifo2", 0666);
	}

	int fd=open("./fifo2",O_WRONLY | O_TRUNC);
	
	while(1){
		char buf[128]={0};
		printf("请输入:");
		scanf("%s", buf);
		while(getchar()!=10);
		write(fd, buf, strlen(buf));
	}
	close(fd);
}

void task_r()
{
	if(access("fifo1", F_OK)==-1){
		mkfifo("./fifo1", 0666);
	}
	int fd=open("./fifo1", O_RDONLY);

	while(1){
		char buf[128]={0};
		int res=read(fd, buf, 128);
		if(res==0){break;}
		printf("\b\b\b\b\b\b\b读取到的消息为:%s\n", buf);
		printf("请输入:");
		fflush(stdout);
	}
	close(fd);
}

void handler(int signum)
{
	if(signum==SIGPIPE){
		printf("管道破裂\n");
		exit(0);
	}
}

void* thread_main(void* arg)
{
	task_r();
}

int main()
{
	signal(SIGPIPE, handler);
	pthread_t id;
	pthread_create(&id, 0, thread_main, 0);
	pthread_detach(id);
	
	task_w();
	return 0;
}


二、请使用共享内存+信号灯集,实现2个进程之间互相聊天

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <semaphore.h>

#define SHM_SIZE 1024  // 共享内存大小
#define SEM_A_NAME "/sem_a"  // 进程A的信号灯名称
#define SEM_B_NAME "/sem_b"  // 进程B的信号灯名称
#define SHM_NAME "/chat_shm"  // 共享内存名称

int main() {
    // 创建共享内存对象
    int shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1) {
        perror("shm_open");
        exit(EXIT_FAILURE);
    }

    // 设置共享内存大小
    if (ftruncate(shm_fd, SHM_SIZE) == -1) {
        perror("ftruncate");
        exit(EXIT_FAILURE);
    }

    // 映射共享内存
    char *shm_ptr = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (shm_ptr == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    // 创建信号灯
    sem_t *sem_a = sem_open(SEM_A_NAME, O_CREAT, 0666, 1);
    sem_t *sem_b = sem_open(SEM_B_NAME, O_CREAT, 0666, 0);
    if (sem_a == SEM_FAILED || sem_b == SEM_FAILED) {
        perror("sem_open");
        exit(EXIT_FAILURE);
    }

    // 进程A和进程B的逻辑
    if (fork() == 0) {
        // 子进程(进程B)
        while (1) {
            sem_wait(sem_b);  // 等待进程A的信号
            printf("Process B received: %s", shm_ptr);
            printf("Process B: ");
            fgets(shm_ptr, SHM_SIZE, stdin);
            sem_post(sem_a);  // 通知进程A
        }
    } else {
        // 父进程(进程A)
        while (1) {
            sem_wait(sem_a);  // 等待进程B的信号
            printf("Process A received: %s", shm_ptr);
            printf("Process A: ");
            fgets(shm_ptr, SHM_SIZE, stdin);
            sem_post(sem_b);  // 通知进程B
        }
    }

    // 清理资源
    sem_close(sem_a);
    sem_close(sem_b);
    sem_unlink(SEM_A_NAME);
    sem_unlink(SEM_B_NAME);
    munmap(shm_ptr, SHM_SIZE);
    shm_unlink(SHM_NAME);

    return 0;
}


三、请实现一个终端的功能,注意需要带有cd功能

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>

char *mygets(char *s, int size)
{
	char *res = fgets(s, size, stdin);
	int len = strlen(s);
	if (s[len-1] == '\n')
	{
		s[len-1] = '\0';
	}
	return s;
}

int main(int argc, const char *argv[])
{
	while(1)
	{
		pid_t pid = fork();
		if(pid > 0)
		{
			wait(0);
		}
		else if(pid == 0)
		{
			char *username = getlogin(); //获取用户名
			char hostname[64] = {0};
			gethostname(hostname, 63); //获取主机名
			char cwd[64] = "";
			getcwd(cwd, 63); //获取当前工作路径
			//\033[ 显示方式 ; 前景色 ; 背景色m
			printf("\033[1;32;10m%s@%s\033[0m:\033[1;34;10m%s\033[0m$ ", username, hostname, cwd);
			fflush(stdout);

			char shell[256] = {0};
			char *cmd[100] = {0};
			mygets(shell, 256);
			
			char *res = NULL;
			int i = 0;
			while(1)
			{
				if(res == NULL)
				{
					res = strtok(shell, " ");
				}
				else
				{
					res = strtok(NULL, " ");
				}

				if(res == NULL)
				{
					break;
				}
				cmd[i] = res;
				i++;
			}

			char pathname[32] = "/bin/";
			strcat(pathname, cmd[0]);

			execvp(cmd[0], cmd);
			printf("%s:未找到命令\n", cmd[0]);
		}
	}
	return 0;
}


四、请使用dup2+fgets+printf实现文件拷贝功能

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

#define BUFFER_SIZE 1024

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <source_file> <destination_file>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 打开源文件
    int src_fd = open(argv[1], O_RDONLY);
    if (src_fd == -1) {
        perror("open source file");
        exit(EXIT_FAILURE);
    }

    // 打开目标文件
    int dest_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (dest_fd == -1) {
        perror("open destination file");
        close(src_fd);
        exit(EXIT_FAILURE);
    }

    // 将源文件的文件描述符复制到标准输入
    if (dup2(src_fd, STDIN_FILENO) == -1) {
        perror("dup2 stdin");
        close(src_fd);
        close(dest_fd);
        exit(EXIT_FAILURE);
    }

    // 将目标文件的文件描述符复制到标准输出
    if (dup2(dest_fd, STDOUT_FILENO) == -1) {
        perror("dup2 stdout");
        close(src_fd);
        close(dest_fd);
        exit(EXIT_FAILURE);
    }

    // 关闭原始文件描述符
    close(src_fd);
    close(dest_fd);

    // 使用 fgets 和 printf 实现文件拷贝
    char buffer[BUFFER_SIZE];
    while (fgets(buffer, BUFFER_SIZE, stdin) != NULL) {
        printf("%s", buffer);
    }

    return 0;
}


五、请使用read和write实现链表保存到文件,以及从文件加载数据到链表中的功能

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

// 链表节点结构体
typedef struct Node {
    int id;
    char name[32];       // 定长字符串,避免动态内存处理
    struct Node *next;
} Node;

// 全局链表头指针
Node *head = NULL;

void save_list_to_file(const char *filename) {
    int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd == -1) {
        perror("open (save)");
        return;
    }

    Node *current = head;
    while (current != NULL) {
        // 写入 id 和 name,不保存 next 指针
        if (write(fd, &current->id, sizeof(int)) != sizeof(int)) {
            perror("write id");
            close(fd);
            return;
        }
        if (write(fd, current->name, sizeof(current->name)) != sizeof(current->name)) {
            perror("write name");
            close(fd);
            return;
        }
        current = current->next;
    }

    close(fd);
    printf("链表已保存到文件.\n");
}


void load_list_from_file(const char *filename) {
    int fd = open(filename, O_RDONLY);
    if (fd == -1) {
        perror("open (load)");
        return;
    }

    // 清空旧链表
    Node *current = head;
    while (current != NULL) {
        Node *temp = current;
        current = current->next;
        free(temp);
    }
    head = NULL;

    Node *prev = NULL;
    while (1) {
        Node *new_node = (Node*)malloc(sizeof(Node));
        if (!new_node) {
            perror("malloc");
            break;
        }

        // 读取 id
        ssize_t bytes_read = read(fd, &new_node->id, sizeof(int));
        if (bytes_read == 0) break;  // 文件结束
        else if (bytes_read != sizeof(int)) {
            perror("read id");
            free(new_node);
            break;
        }

        // 读取 name
        bytes_read = read(fd, new_node->name, sizeof(new_node->name));
        if (bytes_read != sizeof(new_node->name)) {
            perror("read name");
            free(new_node);
            break;
        }

        new_node->next = NULL;

        // 链接到链表
        if (prev == NULL) {
            head = new_node;
        } else {
            prev->next = new_node;
        }
        prev = new_node;
    }

    close(fd);
    printf("链表已从文件加载.\n");
}


void add_node(int id, const char *name) {
    Node *new_node = (Node*)malloc(sizeof(Node));
    new_node->id = id;
    strncpy(new_node->name, name, sizeof(new_node->name));
    new_node->next = head;
    head = new_node;
}


void print_list() {
    Node *current = head;
    while (current != NULL) {
        printf("ID: %d, Name: %s\n", current->id, current->name);
        current = current->next;
    }
}


int main() {
    // 添加测试数据
    add_node(1, "Alice");
    add_node(2, "Bob");
    add_node(3, "Charlie");

    // 保存链表到文件
    save_list_to_file("list.dat");

    // 清空链表(模拟重新加载)
    Node *temp;
    while (head != NULL) {
        temp = head;
        head = head->next;
        free(temp);
    }

    // 从文件加载链表
    load_list_from_file("list.dat");
    print_list();

    return 0;
}


六、请使用互斥锁和信号量分别实现5个线程之间的同步

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#define NUM_THREADS 5

pthread_mutex_t mutex;

void* thread_function(void* arg) {
    int thread_id = *(int*)arg;
    
    // 尝试获取互斥锁
    pthread_mutex_lock(&mutex);
    
    printf("Thread %d is running\n", thread_id);
    sleep(1); // 模拟某些工作
    
    // 释放互斥锁
    pthread_mutex_unlock(&mutex);
    
    free(arg);
    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    
    // 初始化互斥锁
    if (pthread_mutex_init(&mutex, NULL) != 0) {
        printf("Mutex init failed\n");
        return 1;
    }
    
    for (int i = 0; i < NUM_THREADS; i++) {
        int* thread_id = malloc(sizeof(int));
        *thread_id = i;
        // 创建线程
        if (pthread_create(&threads[i], NULL, thread_function, thread_id) != 0) {
            printf("Error creating thread %d\n", i);
            return 1;
        }
    }
    
    // 等待所有线程完成
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    // 销毁互斥锁
    pthread_mutex_destroy(&mutex);
    
    return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define NUM_THREADS 5

sem_t semaphore;

void* thread_function(void* arg) {
    int thread_id = *(int*)arg;
    
    // 等待信号量
    sem_wait(&semaphore);
    
    printf("Thread %d is running\n", thread_id);
    sleep(1); // 模拟某些工作
    
    // 释放信号量
    sem_post(&semaphore);
    
    free(arg);
    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    
    // 初始化信号量,初始值为1
    if (sem_init(&semaphore, 0, 1) != 0) {
        printf("Semaphore init failed\n");
        return 1;
    }
    
    for (int i = 0; i < NUM_THREADS; i++) {
        int* thread_id = malloc(sizeof(int));
        *thread_id = i;
        // 创建线程
        if (pthread_create(&threads[i], NULL, thread_function, thread_id) != 0) {
            printf("Error creating thread %d\n", i);
            return 1;
        }
    }
    
    // 等待所有线程完成
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    // 销毁信号量
    sem_destroy(&semaphore);
    
    return 0;
}


七、请使用条件变量实现2生产者2消费者模型,注意1个生产者在生产的时候,另外一个生产者不能生产

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#define BUFFER_SIZE 10

int buffer[BUFFER_SIZE];
int count = 0; // 缓冲区中项目的数量

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_produce = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_consume = PTHREAD_COND_INITIALIZER;

// 生产者函数
void* producer(void* arg) {
    int producer_id = *(int*)arg;
    
    while (1) {
        // 生产一个项目
        int item = rand() % 100;
        
        // 加锁
        pthread_mutex_lock(&mutex);
        
        // 缓冲区满,等待消费
        while (count == BUFFER_SIZE) {
            pthread_cond_wait(&cond_produce, &mutex);
        }
        
        // 将项目放入缓冲区
        buffer[count] = item;
        count++;
        printf("Producer %d produced item %d, count = %d\n", producer_id, item, count);
        
        // 通知消费者有新项目可用
        pthread_cond_signal(&cond_consume);
        
        // 解锁
        pthread_mutex_unlock(&mutex);
        
        // 模拟生产时间
        sleep(rand() % 3);
    }
    
    return NULL;
}

// 消费者函数
void* consumer(void* arg) {
    int consumer_id = *(int*)arg;
    
    while (1) {
        // 加锁
        pthread_mutex_lock(&mutex);
        
        // 缓冲区空,等待生产
        while (count == 0) {
            pthread_cond_wait(&cond_consume, &mutex);
        }
        
        // 从缓冲区取出项目
        int item = buffer[count - 1];
        count--;
        printf("Consumer %d consumed item %d, count = %d\n", consumer_id, item, count);
        
        // 通知生产者有空间可用
        pthread_cond_signal(&cond_produce);
        
        // 解锁
        pthread_mutex_unlock(&mutex);
        
        // 模拟消费时间
        sleep(rand() % 3);
    }
    
    return NULL;
}

int main() {
    pthread_t producers, consumers;
    int producer_ids = {1, 2};
    int consumer_ids = {1, 2};
    
    // 创建生产者线程
    for (int i = 0; i < 2; i++) {
        if (pthread_create(&producers[i], NULL, producer, &producer_ids[i]) != 0) {
            printf("Error creating producer thread %d\n", i);
            return 1;
        }
    }
    
    // 创建消费者线程
    for (int i = 0; i < 2; i++) {
        if (pthread_create(&consumers[i], NULL, consumer, &consumer_ids[i]) != 0) {
            printf("Error creating consumer thread %d\n", i);
            return 1;
        }
    }
    
    // 等待线程完成
    for (int i = 0; i < 2; i++) {
        pthread_join(producers[i], NULL);
        pthread_join(consumers[i], NULL);
    }
    
    // 销毁互斥锁和条件变量
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond_produce);
    pthread_cond_destroy(&cond_consume);
    
    return 0;
}

八、请写一个双向链表的快速排序函数

九、请用递归实现计算:1+1/3-1/5+1/7-1/9+...1/n 的值,n通过键盘输入

#include <stdio.h>

// 递归函数声明
double alt_ser(int n);

int main() {
    int n;
    double result;

    // 从用户获取输入
    printf("请输入一个正整数n: ");
    scanf("%d", &n);

    // 检查输入是否合法
    if (n <= 0) {
        printf("请输入一个大于0的正整数。\n");
        return 1; // 返回错误码
    }

    // 调用递归函数计算结果
    result = alt_ser(n);

    // 输出结果
    printf("交错级数1 + 1/3 - 1/5 + 1/7 - 1/9 + ... 1/%d的值为: %.15f\n", n, result);

    return 0;
}

// 递归函数定义
double alt_ser(int n) {
    // 基本情况:如果n等于1,返回1
    if (n == 1) {
        return 1.0;
    }
    // 递归情况
    else if (n % 2 == 1) { // 奇数项
        return 1.0 / n + alt_ser(n - 2);
    } else { // 偶数项
        return -1.0 / n + alt_ser(n - 2);
    }
}


十、请写出以下几个数据的类型

// 整数a:
    类型:int

// a的地址:
    类型:int *

// 存放a的数组b:
    类型:int[]

// 存放a的地址的数组c:
    类型:int* []

// b的地址:
    类型:int (*)[]

// c的地址:
    类型:int**

// 指向printf函数的指针d:
    类型:int (*)(const char*, ...)

// 存放d的数组:
    类型:int (**)[]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值