计算机输入输出模块的源码实现通常涉及到底层的硬件操作和系统调用。以下是一个简化的示例,展示了如何在C语言中实现基本的输入输出模块。这个示例包括从键盘读取输入和向屏幕输出内容。
1. 键盘输入模块
#include <stdio.h>
// 函数声明
char read_char();
int main() {
printf("请输入一个字符: ");
char ch = read_char();
printf("你输入的字符是: %c\n", ch);
return 0;
}
// 从键盘读取一个字符
char read_char() {
char ch;
scanf("%c", &ch);
return ch;
}
2. 屏幕输出模块
#include <stdio.h>
// 函数声明
void print_string(const char *str);
int main() {
const char *message = "Hello, World!";
print_string(message);
return 0;
}
// 向屏幕输出一个字符串
void print_string(const char *str) {
printf("%s\n", str);
}
3. 文件输入输出模块
#include <stdio.h>
// 函数声明
void write_to_file(const char *filename, const char *content);
void read_from_file(const char *filename);
int main() {
const char *filename = "example.txt";
const char *content = "这是一个示例文件内容。\n";
// 写入文件
write_to_file(filename, content);
// 读取文件
read_from_file(filename);
return 0;
}
// 向文件写入内容
void write_to_file(const char *filename, const char *content) {
FILE *file = fopen(filename, "w");
if (file == NULL) {
perror("无法打开文件");
return;
}
fputs(content, file);
fclose(file);
}
// 从文件读取内容
void read_from_file(const char *filename) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
perror("无法打开文件");
return;
}
char ch;
while ((ch = fgetc(file)) != EOF) {
putchar(ch);
}
fclose(file);
}
解释
-
键盘输入模块:
read_char
函数使用scanf
从标准输入读取一个字符。
-
屏幕输出模块:
print_string
函数使用printf
向标准输出打印一个字符串。
-
文件输入输出模块:
write_to_file
函数使用fopen
打开文件并以写模式 ("w"
) 写入内容。read_from_file
函数使用fopen
打开文件并以读模式 ("r"
) 读取内容,并逐字符读取直到文件结束。
注意事项
- 这些示例是非常基础的实现,实际应用中可能需要处理更多的错误情况和边界条件。
- 对于更复杂的输入输出需求(如网络通信、设备驱动等),通常需要使用操作系统提供的系统调用或专门的库函数。
希望这些示例能帮助你理解计算机输入输出模块的基本实现原理。如果你有更具体的需求或场景,请提供更多细节,我可以进一步帮助你。
当然,我们可以进一步探讨更复杂的输入输出模块实现,特别是在涉及文件操作、网络通信和多线程环境下的情况。
4. 文件操作进阶
4.1 文件复制
#include <stdio.h>
#include <stdlib.h>
void copy_file(const char *src_filename, const char *dest_filename) {
FILE *src_file = fopen(src_filename, "rb");
if (!src_file) {
perror("无法打开源文件");
return;
}
FILE *dest_file = fopen(dest_filename, "wb");
if (!dest_file) {
perror("无法打开目标文件");
fclose(src_file);
return;
}
char buffer[1024];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), src_file)) > 0) {
fwrite(buffer, 1, bytes_read, dest_file);
}
fclose(src_file);
fclose(dest_file);
}
4.2 文件搜索
#include <stdio.h>
#include <dirent.h>
#include <string.h>
void search_files(const char *directory, const char *pattern) {
DIR *dir = opendir(directory);
if (!dir) {
perror("无法打开目录");
return;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
if (strstr(entry->d_name, pattern)) {
printf("%s/%s\n", directory, entry->d_name);
}
}
closedir(dir);
}
5. 网络通信
5.1 简单的TCP客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
void tcp_client(const char *ip, int port, const char *message) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("无法创建套接字");
return;
}
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
inet_pton(AF_INET, ip, &server_addr.sin_addr);
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("连接失败");
close(sock);
return;
}
send(sock, message, strlen(message), 0);
close(sock);
}
5.2 简单的TCP服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
void tcp_server(int port) {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("无法创建套接字");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("绑定失败");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("监听失败");
exit(EXIT_FAILURE);
}
while (1) {
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("接受连接失败");
exit(EXIT_FAILURE);
}
char buffer[1024] = {0};
read(new_socket, buffer, 1024);
printf("收到消息: %s\n", buffer);
close(new_socket);
}
close(server_fd);
}
6. 多线程输入输出
6.1 多线程文件读写
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *write_to_file(void *arg) {
const char *filename = (const char *)arg;
FILE *file = fopen(filename, "a");
if (!file) {
perror("无法打开文件");
return NULL;
}
for (int i = 0; i < 10; ++i) {
fprintf(file, "线程写入的数据 %d\n", i);
}
fclose(file);
return NULL;
}
int main() {
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, write_to_file, (void *)"file1.txt");
pthread_create(&thread2, NULL, write_to_file, (void *)"file2.txt");
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
总结
以上示例展示了如何在C语言中实现更复杂的输入输出模块,包括文件操作、网络通信和多线程处理。这些示例涵盖了从基础的文件读写到高级的网络编程和并发处理的各个方面。
在实际应用中,你可能需要根据具体需求进一步优化和扩展这些代码。例如,添加错误处理、性能优化、安全性考虑等。希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。
继续深入探讨输入输出模块的高级实现,我们可以考虑以下几个方面:
7. 异步I/O操作
异步I/O允许程序在等待I/O操作完成的同时执行其他任务,从而提高程序的效率和响应性。
7.1 使用select
进行异步文件操作
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
void async_read_file(const char *filename) {
int fd = open(filename, O_RDONLY);
if (fd == -1) {
perror("无法打开文件");
return;
}
fd_set readfds;
struct timeval timeout;
while (1) {
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
timeout.tv_sec = 5;
timeout.tv_usec = 0;
int ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
if (ret == -1) {
perror("select错误");
break;
} else if (ret) {
if (FD_ISSET(fd, &readfds)) {
char buffer[1024];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
if (bytes_read > 0) {
write(STDOUT_FILENO, buffer, bytes_read);
} else {
break;
}
}
} else {
printf("select超时\n");
}
}
close(fd);
}
8. 高级文件系统操作
8.1 文件属性查询
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
void get_file_info(const char *filename) {
struct stat file_stat;
if (stat(filename, &file_stat) < 0) {
perror("无法获取文件信息");
return;
}
printf("文件名: %s\n", filename);
printf("文件大小: %ld bytes\n", file_stat.st_size);
printf("最后修改时间: %s", ctime(&file_stat.st_mtime));
}
9. 网络编程进阶
9.1 使用select
的多客户端TCP服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/select.h>
#define MAX_CLIENTS 10
void tcp_server_multi_client(int port) {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
int client_sockets[MAX_CLIENTS] = {0};
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("无法创建套接字");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("绑定失败");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("监听失败");
exit(EXIT_FAILURE);
}
fd_set readfds;
while (1) {
FD_ZERO(&readfds);
FD_SET(server_fd, &readfds);
int max_sd = server_fd;
for (int i = 0; i < MAX_CLIENTS; i++) {
int sd = client_sockets[i];
if (sd > 0) {
FD_SET(sd, &readfds);
}
if (sd > max_sd) {
max_sd = sd;
}
}
int activity = select(max_sd + 1, &readfds, NULL, NULL, NULL);
if ((activity < 0) && (errno != EINTR)) {
perror("select错误");
}
if (FD_ISSET(server_fd, &readfds)) {
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("接受连接失败");
exit(EXIT_FAILURE);
}
for (int i = 0; i < MAX_CLIENTS; i++) {
if (client_sockets[i] == 0) {
client_sockets[i] = new_socket;
break;
}
}
}
for (int i = 0; i < MAX_CLIENTS; i++) {
int sd = client_sockets[i];
if (FD_ISSET(sd, &readfds)) {
char buffer[1024] = {0};
int valread = read(sd, buffer, 1024);
if (valread == 0) {
getpeername(sd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
printf("客户端 %s:%d 断开连接\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
close(sd);
client_sockets[i] = 0;
} else {
printf("收到来自客户端 %s:%d 的消息: %s\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port), buffer);
}
}
}
}
close(server_fd);
}
10. 多线程与同步机制
10.1 使用互斥锁保护共享资源
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 5
int shared_data = 0;
pthread_mutex_t mutex;
void *thread_function(void *arg) {
int thread_id = *(int *)arg;
pthread_mutex_lock(&mutex);
shared_data += 1;
printf("线程 %d 更新共享数据为 %d\n", thread_id, shared_data);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
int thread_ids[NUM_THREADS];
pthread_mutex_init(&mutex, NULL);
for (int i = 0; i < NUM_THREADS; ++i) {
thread_ids[i] = i;
pthread_create(&threads[i], NULL, thread_function, (void *)&thread_ids[i]);
}
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_join(threads[i], NULL);
}
pthread_mutex_destroy(&mutex);
return 0;
}
总结
以上示例展示了如何在C语言中实现更高级的输入输出模块,包括异步I/O、高级文件系统操作、多客户端网络服务器以及多线程同步机制。这些技术在实际应用中非常有用,可以帮助你构建高效、稳定和安全的系统。
希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。
11. 高级网络编程:非阻塞I/O与事件驱动
11.1 使用epoll
实现高性能服务器
epoll
是Linux特有的高效I/O事件通知机制,适用于高并发网络服务器。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/epoll.h>
#define MAX_EVENTS 10
void setnonblocking(int sockfd) {
int opts;
opts = fcntl(sockfd, F_GETFL);
if (opts < 0) {
perror("fcntl(F_GETFL)");
exit(EXIT_FAILURE);
}
opts = (opts | O_NONBLOCK);
if (fcntl(sockfd, F_SETFL, opts) < 0) {
perror("fcntl(F_SETFL)");
exit(EXIT_FAILURE);
}
}
int main() {
int listen_fd, conn_fd, epoll_fd, nfds, n;
struct epoll_event ev, events[MAX_EVENTS];
struct sockaddr_in server_addr, client_addr;
socklen_t client_len;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(8080);
if (bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("bind");
close(listen_fd);
exit(EXIT_FAILURE);
}
if (listen(listen_fd, SOMAXCONN) < 0) {
perror("listen");
close(listen_fd);
exit(EXIT_FAILURE);
}
epoll_fd = epoll_create1(0);
if (epoll_fd < 0) {
perror("epoll_create1");
close(listen_fd);
exit(EXIT_FAILURE);
}
ev.events = EPOLLIN;
ev.data.fd = listen_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) < 0) {
perror("epoll_ctl: listen_fd");
close(listen_fd);
close(epoll_fd);
exit(EXIT_FAILURE);
}
while (1) {
nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
if (nfds < 0) {
perror("epoll_wait");
break;
}
for (n = 0; n < nfds; ++n) {
if (events[n].data.fd == listen_fd) {
conn_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_len);
if (conn_fd < 0) {
perror("accept");
continue;
}
setnonblocking(conn_fd);
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = conn_fd;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &ev) < 0) {
perror("epoll_ctl: conn_fd");
close(conn_fd);
}
} else {
conn_fd = events[n].data.fd;
char buffer[1024];
int len = read(conn_fd, buffer, sizeof(buffer));
if (len <= 0) {
close(conn_fd);
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, conn_fd, NULL);
} else {
write(conn_fd, buffer, len); // Echo back
}
}
}
}
close(listen_fd);
close(epoll_fd);
return 0;
}
12. 高级文件系统操作:内存映射文件
内存映射文件允许将文件的一部分或全部映射到内存中,从而实现高效的文件读写操作。
12.1 使用mmap
进行内存映射
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void mmap_read_file(const char *filename) {
int fd = open(filename, O_RDONLY);
if (fd == -1) {
perror("无法打开文件");
return;
}
struct stat file_stat;
if (fstat(fd, &file_stat) < 0) {
perror("fstat错误");
close(fd);
return;
}
void *addr = mmap(NULL, file_stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap错误");
close(fd);
return;
}
printf("文件内容:\n%s", (char *)addr);
if (munmap(addr, file_stat.st_size) < 0) {
perror("munmap错误");
}
close(fd);
}
13. 高级多线程编程:条件变量
条件变量用于多线程间的同步,允许线程等待某个条件成立后再继续执行。
13.1 使用条件变量实现生产者-消费者模型
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
int count = 0;
pthread_mutex_t mutex;
pthread_cond_t cond_full;
pthread_cond_t cond_empty;
void *producer(void *arg) {
int item, i;
for (i = 0; i < 20; i++) {
item = i;
pthread_mutex_lock(&mutex);
while (count == BUFFER_SIZE) {
pthread_cond_wait(&cond_full, &mutex);
}
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
count++;
pthread_cond_signal(&cond_empty);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
void *consumer(void *arg) {
int item, i;
for (i = 0; i < 20; i++) {
pthread_mutex_lock(&mutex);
while (count == 0) {
pthread_cond_wait(&cond_empty, &mutex);
}
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
count--;
pthread_cond_signal(&cond_full);
pthread_mutex_unlock(&mutex);
printf("消费: %d\n", item);
}
return NULL;
}
int main() {
pthread_t producer_thread, consumer_thread;
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond_full, NULL);
pthread_cond_init(&cond_empty, NULL);
pthread_create(&producer_thread, NULL, producer, NULL);
pthread_create(&consumer_thread, NULL, consumer, NULL);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond_full);
pthread_cond_destroy(&cond_empty);
return 0;
}
总结
以上示例展示了如何在C语言中实现更高级的网络编程技术(如非阻塞I/O和事件驱动)、文件系统操作(如内存映射文件)以及多线程编程(如条件变量)。这些技术在实际应用中非常有用,可以帮助你构建高效、稳定和安全的系统。
希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。
14. 高级多线程编程:读写锁
读写锁允许多个读线程同时访问共享资源,但只允许一个写线程访问,从而提高并发性能。
14.1 使用读写锁实现高效的并发读写
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_READERS 5
#define NUM_WRITERS 2
int shared_data = 0;
pthread_rwlock_t rwlock;
void *reader(void *arg) {
int id = *(int *)arg;
while (1) {
pthread_rwlock_rdlock(&rwlock);
printf("读者 %d 读取数据: %d\n", id, shared_data);
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
return NULL;
}
void *writer(void *arg) {
int id = *(int *)arg;
while (1) {
pthread_rwlock_wrlock(&rwlock);
shared_data++;
printf("写者 %d 更新数据为 %d\n", id, shared_data);
pthread_rwlock_unlock(&rwlock);
sleep(2);
}
return NULL;
}
int main() {
pthread_t readers[NUM_READERS];
pthread_t writers[NUM_WRITERS];
int reader_ids[NUM_READERS];
int writer_ids[NUM_WRITERS];
pthread_rwlock_init(&rwlock, NULL);
for (int i = 0; i < NUM_READERS; ++i) {
reader_ids[i] = i;
pthread_create(&readers[i], NULL, reader, (void *)&reader_ids[i]);
}
for (int i = 0; i < NUM_WRITERS; ++i) {
writer_ids[i] = i;
pthread_create(&writers[i], NULL, writer, (void *)&writer_ids[i]);
}
for (int i = 0; i < NUM_READERS; ++i) {
pthread_join(readers[i], NULL);
}
for (int i = 0; i < NUM_WRITERS; ++i) {
pthread_join(writers[i], NULL);
}
pthread_rwlock_destroy(&rwlock);
return 0;
}
15. 高级网络编程:TLS/SSL加密通信
TLS/SSL用于在网络通信中提供加密和身份验证,确保数据的安全传输。
15.1 使用OpenSSL库实现简单的TLS服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define PORT 4433
void init_openssl() {
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
}
SSL_CTX *create_context() {
const SSL_METHOD *method;
SSL_CTX *ctx;
method = TLSv1_2_server_method();
ctx = SSL_CTX_new(method);
if (!ctx) {
perror("Unable to create SSL context");
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
return ctx;
}
void configure_context(SSL_CTX *ctx) {
SSL_CTX_set_ecdh_auto(ctx, 1);
if (SSL_CTX_use_certificate_file(ctx, "cert.pem", SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
if (SSL_CTX_use_PrivateKey_file(ctx, "key.pem", SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
}
int main() {
int sock;
struct sockaddr_in addr;
socklen_t len;
SSL_CTX *ctx;
SSL *ssl;
init_openssl();
ctx = create_context();
configure_context(ctx);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PORT);
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
perror("bind");
close(sock);
exit(EXIT_FAILURE);
}
if (listen(sock, SOMAXCONN) < 0) {
perror("listen");
close(sock);
exit(EXIT_FAILURE);
}
while (1) {
len = sizeof(addr);
int client_sock = accept(sock, (struct sockaddr*)&addr, &len);
if (client_sock < 0) {
perror("accept");
continue;
}
ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_sock);
if (SSL_accept(ssl) <= 0) {
ERR_print_errors_fp(stderr);
} else {
char reply[] = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World!";
SSL_write(ssl, reply, strlen(reply));
}
SSL_free(ssl);
close(client_sock);
}
SSL_CTX_free(ctx);
close(sock);
EVP_cleanup();
return 0;
}
总结
以上示例展示了如何在C语言中实现更高级的多线程编程技术(如读写锁)和网络编程技术(如TLS/SSL加密通信)。这些技术在实际应用中非常有用,可以帮助你构建高效、安全和可靠的系统。
希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。
16. 高级文件系统操作:文件锁
文件锁用于在多进程或多线程环境中对文件进行同步访问,防止数据冲突。
16.1 使用文件锁实现进程间文件同步
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>
void lock_file(const char *filename) {
int fd = open(filename, O_RDWR);
if (fd == -1) {
perror("无法打开文件");
return;
}
if (flock(fd, LOCK_EX) == -1) {
perror("文件锁失败");
close(fd);
return;
}
printf("文件已锁定,可以进行写操作\n");
// 模拟写操作
sleep(5);
if (flock(fd, LOCK_UN) == -1) {
perror("解锁文件失败");
}
close(fd);
}
int main() {
lock_file("shared_file.txt");
return 0;
}
17. 高级多线程编程:线程池
线程池用于管理和复用线程,减少线程创建和销毁的开销,提高系统性能。
17.1 实现一个简单的线程池
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 5
#define MAX_TASKS 10
typedef struct {
void (*function)(void *);
void *argument;
} task_t;
typedef struct {
task_t tasks[MAX_TASKS];
int task_count;
pthread_mutex_t lock;
pthread_cond_t cond;
int shutdown;
} thread_pool_t;
void *worker(void *arg) {
thread_pool_t *pool = (thread_pool_t *)arg;
while (1) {
pthread_mutex_lock(&pool->lock);
while (pool->task_count == 0 && !pool->shutdown) {
pthread_cond_wait(&pool->cond, &pool->lock);
}
if (pool->shutdown) {
pthread_mutex_unlock(&pool->lock);
pthread_exit(NULL);
}
task_t task = pool->tasks[--pool->task_count];
pthread_mutex_unlock(&pool->lock);
task.function(task.argument);
}
}
void thread_pool_init(thread_pool_t *pool) {
pool->task_count = 0;
pool->shutdown = 0;
pthread_mutex_init(&pool->lock, NULL);
pthread_cond_init(&pool->cond, NULL);
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_create(&threads[i], NULL, worker, pool);
}
}
void thread_pool_add_task(thread_pool_t *pool, void (*function)(void *), void *argument) {
pthread_mutex_lock(&pool->lock);
if (pool->task_count < MAX_TASKS) {
pool->tasks[pool->task_count].function = function;
pool->tasks[pool->task_count].argument = argument;
pool->task_count++;
pthread_cond_signal(&pool->cond);
}
pthread_mutex_unlock(&pool->lock);
}
void thread_pool_shutdown(thread_pool_t *pool) {
pthread_mutex_lock(&pool->lock);
pool->shutdown = 1;
pthread_cond_broadcast(&pool->cond);
pthread_mutex_unlock(&pool->lock);
}
void example_task(void *arg) {
int id = *(int *)arg;
printf("任务 %d 正在执行\n", id);
sleep(1);
}
int main() {
thread_pool_t pool;
thread_pool_init(&pool);
int task_ids[MAX_TASKS];
for (int i = 0; i < MAX_TASKS; ++i) {
task_ids[i] = i;
thread_pool_add_task(&pool, example_task, &task_ids[i]);
}
sleep(10);
thread_pool_shutdown(&pool);
return 0;
}
总结
以上示例展示了如何在C语言中实现更高级的文件系统操作(如文件锁)和多线程编程技术(如线程池)。这些技术在实际应用中非常有用,可以帮助你构建高效、安全和可靠的系统。
希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。
18. 高级网络编程:WebSocket服务器
WebSocket是一种在单个TCP连接上进行全双工通信的协议,适用于实时通信应用。
18.1 使用libwebsockets
库实现简单的WebSocket服务器
首先,确保你已经安装了libwebsockets
库。如果没有安装,可以使用包管理器进行安装,例如在Ubuntu上:
sudo apt-get install libwebsockets-dev
然后,编写WebSocket服务器代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libwebsockets.h>
#define LWS_CALLBACK_ESTABLISHED 1
#define LWS_CALLBACK_RECEIVE 2
static int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
printf("WebSocket connection established\n");
break;
case LWS_CALLBACK_RECEIVE:
printf("Received message: %.*s\n", (int)len, (char *)in);
lws_write(wsi, (unsigned char *)in, len, LWS_WRITE_TEXT);
break;
default:
break;
}
return 0;
}
static const struct lws_protocols protocols[] = {
{
"http",
callback_http,
0,
0,
},
{ NULL, NULL, 0, 0 } /* terminator */
};
int main(int argc, char *argv[]) {
struct lws_context_creation_info info;
struct lws_context *context;
const char *interface = NULL;
memset(&info, 0, sizeof info);
info.port = 8080;
info.protocols = protocols;
info.gid = -1;
info.uid = -1;
context = lws_create_context(&info);
if (!context) {
fprintf(stderr, "lws init failed\n");
return -1;
}
while (1) {
lws_service(context, 1000);
}
lws_context_destroy(context);
return 0;
}
编译并运行WebSocket服务器:
gcc -o websocket_server websocket_server.c -lwebsockets
./websocket_server
19. 高级文件系统操作:内存映射文件的并发访问
内存映射文件允许多个进程同时访问同一个文件的不同部分,从而实现高效的并发读写操作。
19.1 使用mmap
和文件锁实现并发访问
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>
void concurrent_access(const char *filename) {
int fd = open(filename, O_RDWR);
if (fd == -1) {
perror("无法打开文件");
return;
}
struct stat file_stat;
if (fstat(fd, &file_stat) < 0) {
perror("fstat错误");
close(fd);
return;
}
void *addr = mmap(NULL, file_stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap错误");
close(fd);
return;
}
// 模拟并发读写
flock(fd, LOCK_EX);
sprintf((char *)addr, "Concurrent access data");
flock(fd, LOCK_UN);
if (munmap(addr, file_stat.st_size) < 0) {
perror("munmap错误");
}
close(fd);
}
int main() {
concurrent_access("shared_file.txt");
return 0;
}
总结
以上示例展示了如何在C语言中实现更高级的网络编程技术(如WebSocket服务器)和文件系统操作(如内存映射文件的并发访问)。这些技术在实际应用中非常有用,可以帮助你构建高效、安全和可靠的系统。
希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。
20. 高级多线程编程:无锁数据结构
无锁数据结构通过使用原子操作和内存屏障来实现线程安全,避免了传统锁机制的开销和潜在的死锁问题。
20.1 实现一个无锁队列
#include <stdio.h>
#include <stdlib.h>
#include <stdatomic.h>
#include <stdbool.h>
typedef struct Node {
int value;
struct Node *next;
} Node;
typedef struct {
Node *head;
Node *tail;
} LockFreeQueue;
void init_queue(LockFreeQueue *queue) {
Node *dummy = (Node *)malloc(sizeof(Node));
dummy->next = NULL;
atomic_init(&queue->head, dummy);
atomic_init(&queue->tail, dummy);
}
bool enqueue(LockFreeQueue *queue, int value) {
Node *new_node = (Node *)malloc(sizeof(Node));
if (!new_node) return false;
new_node->value = value;
new_node->next = NULL;
Node *prev_tail;
Node *null_node = NULL;
do {
prev_tail = atomic_load(&queue->tail);
Node *next = atomic_load(&prev_tail->next);
if (prev_tail == atomic_load(&queue->tail)) {
if (next == NULL) {
if (atomic_compare_exchange_weak(&prev_tail->next, &next, new_node)) {
break;
}
} else {
atomic_compare_exchange_weak(&queue->tail, &prev_tail, next);
}
}
} while (true);
atomic_compare_exchange_weak(&queue->tail, &prev_tail, new_node);
return true;
}
bool dequeue(LockFreeQueue *queue, int *value) {
do {
Node *first = atomic_load(&queue->head);
Node *last = atomic_load(&queue->tail);
Node *next = atomic_load(&first->next);
if (first == atomic_load(&queue->head)) {
if (first == last) {
if (next == NULL) return false; // Queue is empty
atomic_compare_exchange_weak(&queue->tail, &last, next);
} else {
*value = next->value;
if (atomic_compare_exchange_weak(&queue->head, &first, next)) {
break;
}
}
}
} while (true);
free(first);
return true;
}
int main() {
LockFreeQueue queue;
init_queue(&queue);
enqueue(&queue, 1);
enqueue(&queue, 2);
enqueue(&queue, 3);
int value;
while (dequeue(&queue, &value)) {
printf("Dequeued: %d\n", value);
}
return 0;
}
21. 高级网络编程:QUIC协议
QUIC(Quick UDP Internet Connections)是一种基于UDP的传输层协议,旨在减少连接建立时间和提高传输可靠性。
21.1 使用nghttp3
库实现简单的QUIC客户端
首先,确保你已经安装了nghttp3
库。如果没有安装,可以使用包管理器进行安装,例如在Ubuntu上:
sudo apt-get install libnghttp3-dev
然后,编写QUIC客户端代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <nghttp3/nghttp3.h>
void quic_client(const char *url) {
nghttp3_conn *conn;
nghttp3_addrinfo hints, *res;
int rv;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
rv = nghttp3_getaddrinfo(url, &hints, &res);
if (rv != 0) {
fprintf(stderr, "nghttp3_getaddrinfo failed: %s\n", nghttp3_strerror(rv));
return;
}
conn = nghttp3_conn_new(nghttp3_conn_type_client, NULL, NULL);
if (!conn) {
fprintf(stderr, "nghttp3_conn_new failed\n");
nghttp3_freeaddrinfo(res);
return;
}
rv = nghttp3_conn_connect(conn, res);
if (rv != 0) {
fprintf(stderr, "nghttp3_conn_connect failed: %s\n", nghttp3_strerror(rv));
nghttp3_conn_del(conn);
nghttp3_freeaddrinfo(res);
return;
}
// 发送和接收数据
// ...
nghttp3_conn_del(conn);
nghttp3_freeaddrinfo(res);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <url>\n", argv[0]);
return 1;
}
quic_client(argv[1]);
return 0;
}
编译并运行QUIC客户端:
gcc -o quic_client quic_client.c -lnghttp3
./quic_client https://example.com
总结
以上示例展示了如何在C语言中实现更高级的多线程编程技术(如无锁数据结构)和网络编程技术(如QUIC协议)。这些技术在实际应用中非常有用,可以帮助你构建高效、安全和可靠的系统。
希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。
22. 高级文件系统操作:分布式文件系统
分布式文件系统允许多个计算机节点通过网络共享文件和存储资源,提供高可用性、可扩展性和容错性。
22.1 使用GlusterFS实现简单的分布式文件系统
GlusterFS是一个开源的分布式文件系统,可以通过简单的配置实现文件的分布式存储和管理。
-
安装GlusterFS
在所有节点上安装GlusterFS:
sudo apt-get update sudo apt-get install glusterfs-server
-
启动GlusterFS服务
在所有节点上启动GlusterFS服务:
sudo systemctl start glusterd sudo systemctl enable glusterd
-
配置GlusterFS集群
在一个节点上执行以下命令来配置集群:
sudo gluster peer probe <node2_ip> sudo gluster peer probe <node3_ip>
-
创建分布式卷
创建一个分布式卷,例如:
sudo gluster volume create distributed_vol transport tcp <node1_ip>:<port> <node2_ip>:<port> <node3_ip>:<port> force
-
启动卷
启动创建的卷:
sudo gluster volume start distributed_vol
-
挂载卷
在客户端节点上挂载分布式卷:
sudo mount -t glusterfs <node1_ip>:/distributed_vol /mnt/glusterfs
23. 高级多线程编程:线程池与任务队列
线程池与任务队列结合使用可以提高多线程程序的性能和可维护性。
23.1 实现一个带有任务队列的线程池
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 5
#define MAX_TASKS 10
typedef struct {
void (*function)(void *);
void *argument;
} task_t;
typedef struct {
task_t tasks[MAX_TASKS];
int task_count;
pthread_mutex_t lock;
pthread_cond_t cond;
int shutdown;
} thread_pool_t;
void *worker(void *arg) {
thread_pool_t *pool = (thread_pool_t *)arg;
while (1) {
pthread_mutex_lock(&pool->lock);
while (pool->task_count == 0 && !pool->shutdown) {
pthread_cond_wait(&pool->cond, &pool->lock);
}
if (pool->shutdown) {
pthread_mutex_unlock(&pool->lock);
pthread_exit(NULL);
}
task_t task = pool->tasks[--pool->task_count];
pthread_mutex_unlock(&pool->lock);
task.function(task.argument);
}
}
void thread_pool_init(thread_pool_t *pool) {
pool->task_count = 0;
pool->shutdown = 0;
pthread_mutex_init(&pool->lock, NULL);
pthread_cond_init(&pool->cond, NULL);
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_create(&threads[i], NULL, worker, pool);
}
}
void thread_pool_add_task(thread_pool_t *pool, void (*function)(void *), void *argument) {
pthread_mutex_lock(&pool->lock);
if (pool->task_count < MAX_TASKS) {
pool->tasks[pool->task_count].function = function;
pool->tasks[pool->task_count].argument = argument;
pool->task_count++;
pthread_cond_signal(&pool->cond);
}
pthread_mutex_unlock(&pool->lock);
}
void thread_pool_shutdown(thread_pool_t *pool) {
pthread_mutex_lock(&pool->lock);
pool->shutdown = 1;
pthread_cond_broadcast(&pool->cond);
pthread_mutex_unlock(&pool->lock);
}
void example_task(void *arg) {
int id = *(int *)arg;
printf("任务 %d 正在执行\n", id);
sleep(1);
}
int main() {
thread_pool_t pool;
thread_pool_init(&pool);
int task_ids[MAX_TASKS];
for (int i = 0; i < MAX_TASKS; ++i) {
task_ids[i] = i;
thread_pool_add_task(&pool, example_task, &task_ids[i]);
}
sleep(10);
thread_pool_shutdown(&pool);
return 0;
}
总结
以上示例展示了如何在C语言中实现更高级的文件系统操作(如分布式文件系统)和多线程编程技术(如线程池与任务队列)。这些技术在实际应用中非常有用,可以帮助你构建高效、安全和可靠的系统。
希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。
24. 高级网络编程:gRPC服务端和客户端
gRPC是一个高性能、开源和通用的RPC框架,基于HTTP/2协议和Protocol Buffers序列化协议。
24.1 定义gRPC服务和消息
首先,定义一个.proto
文件来描述服务和消息:
syntax = "proto3";
package example;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
24.2 生成gRPC代码
使用protoc
编译器和gRPC插件生成C语言代码:
protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` example.proto
24.3 实现gRPC服务端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include "example.grpc.pb-c.h"
typedef struct {
grpc_server *server;
} server_state;
void say_hello(grpc_exec_ctx *exec_ctx, void *tag, grpc_error *error) {
example_HelloReply reply;
example_HelloRequest request;
memset(&request, 0, sizeof(request));
memset(&reply, 0, sizeof(reply));
grpc_byte_buffer *bb = grpc_server_recv_message(exec_ctx, tag, NULL);
grpc_byte_buffer_reader reader;
grpc_byte_buffer_reader_init(&reader, bb);
char *name = grpc_byte_buffer_reader_read_string(&reader);
reply.message = g_strdup_printf("Hello, %s!", name);
g_free(name);
grpc_server_send_message(exec_ctx, tag, (grpc_byte_buffer *)&reply, NULL);
}
void server_main(server_state *state) {
grpc_server *server = grpc_server_create(NULL, NULL);
example_Greeter_Service *service = example_Greeter_Service_new();
grpc_server_register_service(server, example_Greeter_Service_method_table(), service);
grpc_server_bind(server, "0.0.0.0:50051", NULL);
grpc_server_start(server);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_server_run_insecurely(server, &exec_ctx);
grpc_exec_ctx_finish(&exec_ctx);
example_Greeter_Service_destroy(service);
grpc_server_destroy(server);
}
int main(int argc, char **argv) {
server_state state;
memset(&state, 0, sizeof(state));
server_main(&state);
return 0;
}
24.4 实现gRPC客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include "example.grpc.pb-c.h"
void run_client() {
grpc_channel *channel = grpc_insecure_channel_create("localhost:50051", NULL, NULL);
example_Greeter_Client client = example_Greeter_Client_new(channel);
example_HelloRequest request;
memset(&request, 0, sizeof(request));
request.name = g_strdup("World");
example_HelloReply reply;
memset(&reply, 0, sizeof(reply));
grpc_call *call = example_Greeter_Call_create(client, &request, say_hello_callback, &reply, NULL);
grpc_call_start_batch(call, &batch, 1, NULL, NULL);
grpc_call_wait(call, NULL);
grpc_call_destroy(call);
g_print("Greeting: %s\n", reply.message);
g_free(reply.message);
example_Greeter_Client_destroy(client);
grpc_channel_destroy(channel);
}
int main(int argc, char **argv) {
run_client();
return 0;
}
25. 高级多线程编程:并发数据结构库
并发数据结构库提供了一系列线程安全的数据结构和算法,用于在多线程环境中高效地进行数据操作。
25.1 使用tbb
库实现并发队列
Intel Threading Building Blocks (TBB) 是一个强大的并行编程库,提供了多种并发数据结构。
首先,安装TBB库:
sudo apt-get install libtbb-dev
然后,编写并发队列示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <tbb/concurrent_queue.h>
typedef struct {
int value;
} task_t;
tbb::concurrent_queue<task_t> queue;
void producer() {
for (int i = 0; i < 10; ++i) {
task_t task;
task.value = i;
queue.push(task);
printf("Produced: %d\n", i);
}
}
void consumer() {
task_t task;
while (true) {
if (queue.try_pop(task)) {
printf("Consumed: %d\n", task.value);
} else {
usleep(100);
}
}
}
int main() {
pthread_t producer_thread, consumer_thread;
pthread_create(&producer_thread, NULL, (void *(*)(void *))producer, NULL);
pthread_create(&consumer_thread, NULL, (void *(*)(void *))consumer, NULL);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
return 0;
}
总结
以上示例展示了如何在C语言中实现更高级的网络编程技术(如gRPC服务端和客户端)和多线程编程技术(如并发数据结构库)。这些技术在实际应用中非常有用,可以帮助你构建高效、安全和可靠的系统。
希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。
26. 高级文件系统操作:使用FUSE实现用户空间文件系统
FUSE(Filesystem in Userspace)允许用户在用户空间实现文件系统,而无需修改内核代码。
26.1 实现一个简单的FUSE文件系统
首先,安装FUSE库和开发包:
sudo apt-get install libfuse-dev
然后,编写一个简单的FUSE文件系统示例代码:
#define FUSE_USE_VERSION 30
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
static const char *root = "/tmp/fuse_example";
static int getattr(const char *path, struct stat *stbuf) {
char full_path[1024];
snprintf(full_path, sizeof(full_path), "%s%s", root, path);
if (lstat(full_path, stbuf) == -1) {
return -errno;
}
return 0;
}
static int readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) {
char full_path[1024];
snprintf(full_path, sizeof(full_path), "%s%s", root, path);
DIR *dp;
struct dirent *de;
dp = opendir(full_path);
if (dp == NULL) {
return -errno;
}
while ((de = readdir(dp)) != NULL) {
struct stat st;
memset(&st, 0, sizeof(st));
st.st_ino = de->d_ino;
st.st_mode = de->d_type << 12;
if (filler(buf, de->d_name, &st, 0)) {
break;
}
}
closedir(dp);
return 0;
}
static struct fuse_operations operations = {
.getattr = getattr,
.readdir = readdir,
};
int main(int argc, char *argv[]) {
return fuse_main(argc, argv, &operations, NULL);
}
编译并运行FUSE文件系统:
gcc -o fuse_example fuse_example.c -lfuse
mkdir /tmp/fuse_example
./fuse_example -f /mnt/fuse_example
27. 高级多线程编程:使用OpenMP进行并行计算
OpenMP是一个用于共享内存并行编程的API,可以轻松地将循环并行化。
27.1 使用OpenMP实现并行矩阵乘法
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
#define N 1000
void matrix_multiply(double *A, double *B, double *C, int n) {
#pragma omp parallel for collapse(2)
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
C[i * n + j] = 0;
for (int k = 0; k < n; ++k) {
C[i * n + j] += A[i * n + k] * B[k * n + j];
}
}
}
}
int main() {
double *A = (double *)malloc(N * N * sizeof(double));
double *B = (double *)malloc(N * N * sizeof(double));
double *C = (double *)malloc(N * N * sizeof(double));
// 初始化矩阵A和B
for (int i = 0; i < N * N; ++i) {
A[i] = rand() % 100;
B[i] = rand() % 100;
}
double start_time = omp_get_wtime();
matrix_multiply(A, B, C, N);
double end_time = omp_get_wtime();
printf("Matrix multiplication time: %f seconds\n", end_time - start_time);
free(A);
free(B);
free(C);
return 0;
}
总结
以上示例展示了如何在C语言中实现更高级的文件系统操作(如使用FUSE实现用户空间文件系统)和多线程编程技术(如使用OpenMP进行并行计算)。这些技术在实际应用中非常有用,可以帮助你构建高效、安全和可靠的系统。
希望这些示例能为你提供更多的灵感和参考。如果你有特定的需求或问题,请随时提出,我会尽力帮助你解决。