一、请使用消息队列实现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, ¤t->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 (**)[]