MST

星途 面试题库

面试题:C语言实现复杂文件描述符权限控制场景

假设有一个C语言程序,需要管理多个文件描述符,并且不同的文件描述符在不同的时间段要有不同的权限组合(比如在程序启动阶段某些文件描述符只能读,在数据处理阶段部分文件描述符变为可读可写,在程序收尾阶段又要修改为特定的权限)。同时,要考虑到多线程环境下对这些文件描述符权限操作的线程安全问题。请设计一个完整的解决方案,包括数据结构、函数实现以及对线程安全机制的运用,并给出关键代码。
13.5万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

1. 数据结构设计

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

// 定义文件描述符权限结构体
typedef struct {
    int fd; // 文件描述符
    int current_permissions; // 当前权限
    pthread_mutex_t mutex; // 互斥锁,用于线程安全
} FileDescriptorInfo;

// 定义一个结构体来管理所有文件描述符
typedef struct {
    FileDescriptorInfo *fds;
    int count;
} FileDescriptorManager;

2. 函数实现

初始化函数

// 初始化文件描述符管理器
FileDescriptorManager* createFileDescriptorManager(int num_fds) {
    FileDescriptorManager *manager = (FileDescriptorManager*)malloc(sizeof(FileDescriptorManager));
    if (!manager) {
        perror("malloc");
        return NULL;
    }
    manager->count = num_fds;
    manager->fds = (FileDescriptorInfo*)malloc(num_fds * sizeof(FileDescriptorInfo));
    if (!manager->fds) {
        perror("malloc");
        free(manager);
        return NULL;
    }

    for (int i = 0; i < num_fds; i++) {
        manager->fds[i].fd = -1;
        manager->fds[i].current_permissions = 0;
        if (pthread_mutex_init(&manager->fds[i].mutex, NULL) != 0) {
            perror("pthread_mutex_init");
            for (int j = 0; j < i; j++) {
                pthread_mutex_destroy(&manager->fds[j].mutex);
            }
            free(manager->fds);
            free(manager);
            return NULL;
        }
    }
    return manager;
}

设置文件描述符函数

// 设置文件描述符
int setFileDescriptor(FileDescriptorManager *manager, int index, int new_fd) {
    if (index < 0 || index >= manager->count) {
        return -1;
    }
    pthread_mutex_lock(&manager->fds[index].mutex);
    manager->fds[index].fd = new_fd;
    pthread_mutex_unlock(&manager->fds[index].mutex);
    return 0;
}

设置权限函数

// 设置文件描述符权限
int setPermissions(FileDescriptorManager *manager, int index, int new_permissions) {
    if (index < 0 || index >= manager->count) {
        return -1;
    }
    pthread_mutex_lock(&manager->fds[index].mutex);
    manager->fds[index].current_permissions = new_permissions;
    if (fcntl(manager->fds[index].fd, F_SETFL, new_permissions) == -1) {
        perror("fcntl");
        pthread_mutex_unlock(&manager->fds[index].mutex);
        return -1;
    }
    pthread_mutex_unlock(&manager->fds[index].mutex);
    return 0;
}

获取权限函数

// 获取文件描述符权限
int getPermissions(FileDescriptorManager *manager, int index) {
    if (index < 0 || index >= manager->count) {
        return -1;
    }
    int permissions;
    pthread_mutex_lock(&manager->fds[index].mutex);
    permissions = manager->fds[index].current_permissions;
    pthread_mutex_unlock(&manager->fds[index].mutex);
    return permissions;
}

销毁函数

// 销毁文件描述符管理器
void destroyFileDescriptorManager(FileDescriptorManager *manager) {
    for (int i = 0; i < manager->count; i++) {
        pthread_mutex_destroy(&manager->fds[i].mutex);
        if (manager->fds[i].fd != -1) {
            close(manager->fds[i].fd);
        }
    }
    free(manager->fds);
    free(manager);
}

3. 线程安全机制运用示例

// 线程函数示例
void* threadFunction(void* arg) {
    FileDescriptorManager *manager = (FileDescriptorManager*)arg;
    // 获取文件描述符0的权限
    int permissions = getPermissions(manager, 0);
    if (permissions != -1) {
        printf("Thread: File descriptor 0 has permissions: %d\n", permissions);
    }
    // 设置文件描述符0的权限
    if (setPermissions(manager, 0, O_RDWR) == 0) {
        printf("Thread: Set file descriptor 0 to read - write permissions\n");
    }
    return NULL;
}

4. 主函数示例

int main() {
    FileDescriptorManager *manager = createFileDescriptorManager(2);
    if (!manager) {
        return 1;
    }
    // 假设打开两个文件
    int fd1 = open("file1.txt", O_RDONLY);
    int fd2 = open("file2.txt", O_RDONLY);
    if (fd1 == -1 || fd2 == -1) {
        perror("open");
        destroyFileDescriptorManager(manager);
        return 1;
    }
    setFileDescriptor(manager, 0, fd1);
    setFileDescriptor(manager, 1, fd2);
    // 设置文件描述符0在启动阶段为只读
    setPermissions(manager, 0, O_RDONLY);
    // 设置文件描述符1在启动阶段为只读
    setPermissions(manager, 1, O_RDONLY);

    pthread_t thread;
    if (pthread_create(&thread, NULL, threadFunction, manager) != 0) {
        perror("pthread_create");
        destroyFileDescriptorManager(manager);
        close(fd1);
        close(fd2);
        return 1;
    }
    if (pthread_join(thread, NULL) != 0) {
        perror("pthread_join");
    }
    // 收尾阶段,例如设置文件描述符0为只写
    setPermissions(manager, 0, O_WRONLY);
    destroyFileDescriptorManager(manager);
    close(fd1);
    close(fd2);
    return 0;
}

上述代码通过定义FileDescriptorInfo结构体来管理每个文件描述符及其权限,并使用互斥锁保证线程安全。FileDescriptorManager结构体用于管理所有文件描述符。通过一系列函数实现对文件描述符及其权限的操作,在多线程环境下能够安全地对文件描述符的权限进行动态调整。