opened too many files

本文介绍了在Linux系统中,进程及系统级别的文件描述符限制,包括如何检查当前限制数及如何诊断因打开过多文件导致的问题。通过使用ulimit-a、lsof-ppid等命令,可以帮助开发者定位并解决文件描述符耗尽的问题。

opened too many files

linux把socket当做文件管理,一个socket就是一个文件描述符,同时linux对文件描述符分别在进程和系统级别进行限制,也就是说一个进程打开多少个文件是受限制的,同时操作系统中所有进程打开的文件数也受限制。
通常出现此问题是由于程序中打开了文件流或者socket,没有关闭,导致超过,进程内最大文件数限制;
使用ulimit -a 查看限制数

[root@localhost ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 30197
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024 //最多打开1024个文件
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 30197
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

然后使用lsof -p pid 来查看进程打开的文件描述符,看看什么样的
这里写图片描述
然后使用lsof -p pid|grep keyword|wc -l 查看某类型的文件描述符一共打开多少;
基于以上3个步骤,基本可以确定是打开文件过多导致,修复办法就是找到程序中,操作文件或socket的地方,确保使用完毕后关闭流或socket

参考

http://langyu.iteye.com/blog/763247
http://bbs.youkuaiyun.com/topics/230037148
http://blog.youkuaiyun.com/kongxx/article/details/6405914

题目:本设计使用C语言模拟一个单用户的二级文件管理系统,支持文件与目录的创建、删除、读写等操作,并实现文件的物理存储与目录管理。 实现要求: (1)在磁盘上建立一个文件模拟磁盘分区。 (2)空闲空间管理可使用位示图,存储分配可采用链接等方法。 (3)支持一级或二级目录结构,每项含文件名、地址、长度等。 (4)支持命令操作:login、dir、create、delete、open、close、read、write、exit (5)可扩展实现文件夹的增删功能(可部分实现) #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_BLOCKS 1024 // 磁盘总块数 #define BLOCK_SIZE 512 // 块大小 #define DISK_FILE "disk.bin"// 虚拟磁盘文件名 #define MAX_FILES 100 // 最大文件数 #define MAX_OPEN_FILES 10 // 最多打开文件数 // 文件控制块 FCB typedef struct { char name[64]; // 文件名 int start_block; // 起始块号 int length; // 占用块数 } FileControlBlock; // 全局变量 FileControlBlock root_dir[MAX_FILES]; // 根目录表 int bitmap[MAX_BLOCKS] = {0}; // 位示图 FILE *disk_file; // 磁盘文件指针 int logged_in = 0; // 登录状态 int open_files[MAX_OPEN_FILES][2]; // [fd][index, pos] // 初始化磁盘 void init_disk() { disk_file = fopen(DISK_FILE, "rb+"); if (!disk_file) { disk_file = fopen(DISK_FILE, "wb+"); char zero[BLOCK_SIZE] = {0}; for (int i = 0; i < MAX_BLOCKS; ++i) fwrite(zero, BLOCK_SIZE, 1, disk_file); } } // 初始化根目录 void init_root_directory() { for (int i = 0; i < MAX_FILES; ++i) { root_dir[i].name[0] = '\0'; root_dir[i].start_block = -1; root_dir[i].length = 0; } for (int i = 0; i < MAX_OPEN_FILES; ++i) open_files[i][0] = open_files[i][1] = -1; } // 读取一个块 void read_block(int block_num, void* buffer) { fseek(disk_file, block_num * BLOCK_SIZE, SEEK_SET); fread(buffer, BLOCK_SIZE, 1, disk_file); } // 写入一个块 void write_block(int block_num, const void* buffer) { fseek(disk_file, block_num * BLOCK_SIZE, SEEK_SET); fwrite(buffer, BLOCK_SIZE, 1, disk_file); } // 分配一个空闲块 int allocate_block() { for (int i = 0; i < MAX_BLOCKS; ++i) { if (!bitmap[i]) { bitmap[i] = 1; return i; } } return -1; } // 释放一个块 void free_block(int block_num) { if (block_num >= 0 && block_num < MAX_BLOCKS) bitmap[block_num] = 0; } // 查找文件是否存在 int find_file(const char* filename) { for (int i = 0; i < MAX_FILES; ++i) { if (root_dir[i].start_block != -1 && strcmp(root_dir[i].name, filename) == 0) return i; } return -1; } // 获取一个可用的 fd int get_free_fd() { for (int i = 0; i < MAX_OPEN_FILES; ++i) if (open_files[i][0] == -1) return i; return -1; } // login 命令 void cmd_login() { if (logged_in) { printf("Already logged in.\n"); return; } printf("Login successful.\n"); logged_in = 1; } // dir 命令 void cmd_dir() { if (!logged_in) { printf("Please login first.\n"); return; } printf("Directory:\n"); for (int i = 0; i < MAX_FILES; ++i) { if (root_dir[i].start_block != -1 && root_dir[i].name[0] != '\0') printf("- %s (%d blocks)\n", root_dir[i].name, root_dir[i].length); } } // create 命令 void cmd_create(const char* filename) { if (!logged_in) { printf("Please login first.\n"); return; } if (find_file(filename) != -1) { printf("File already exists.\n"); return; } int index = -1; for (int i = 0; i < MAX_FILES; ++i) { if (root_dir[i].start_block == -1) { index = i; break; } } if (index == -1) { printf("Directory full.\n"); return; } int block = allocate_block(); if (block == -1) { printf("Disk full.\n"); return; } strcpy(root_dir[index].name, filename); root_dir[index].start_block = block; root_dir[index].length = 1; char zero[BLOCK_SIZE] = {0}; write_block(block, zero); printf("File created: %s\n", filename); } // delete 命令 void cmd_delete(const char* filename) { if (!logged_in) { printf("Please login first.\n"); return; } int index = find_file(filename); if (index == -1) { printf("File not found.\n"); return; } FileControlBlock fcb = root_dir[index]; for (int i = 0; i < fcb.length; ++i) free_block(fcb.start_block + i); root_dir[index].start_block = -1; root_dir[index].length = 0; root_dir[index].name[0] = '\0'; printf("File deleted: %s\n", filename); } // open 命令 void cmd_open(const char* filename) { if (!logged_in) { printf("Please login first.\n"); return; } int index = find_file(filename); if (index == -1) { printf("File not found.\n"); return; } int fd = get_free_fd(); if (fd == -1) { printf("Too many open files.\n"); return; } open_files[fd][0] = index; open_files[fd][1] = 0; printf("File opened with fd=%d\n", fd); } // close 命令 void cmd_close(int fd) { if (fd < 0 || fd >= MAX_OPEN_FILES || open_files[fd][0] == -1) { printf("Invalid file descriptor.\n"); return; } open_files[fd][0] = -1; printf("File closed.\n"); } // seek 命令 void cmd_seek(int fd, int offset) { if (fd < 0 || fd >= MAX_OPEN_FILES || open_files[fd][0] == -1) { printf("Invalid file descriptor.\n"); return; } open_files[fd][1] = offset; printf("File pointer set to %d\n", offset); } // read 命令 void cmd_read(int fd, int size) { if (fd < 0 || fd >= MAX_OPEN_FILES || open_files[fd][0] == -1) { printf("Invalid file descriptor.\n"); return; } int index = open_files[fd][0]; int pos = open_files[fd][1]; FileControlBlock fcb = root_dir[index]; char result[size + 1]; memset(result, 0, sizeof(result)); int total_read = 0; int current_block = pos / BLOCK_SIZE; int offset = pos % BLOCK_SIZE; while (total_read < size && current_block < fcb.length) { char buffer[BLOCK_SIZE]; read_block(fcb.start_block + current_block, buffer); int available = BLOCK_SIZE - offset; int to_copy = (available < size - total_read) ? available : (size - total_read); memcpy(result + total_read, buffer + offset, to_copy); total_read += to_copy; current_block++; offset = 0; } result[total_read] = '\0'; open_files[fd][1] = pos + total_read; printf("Read: %s\n", result); } // write 命令 void cmd_write(int fd, const char* data) { if (fd < 0 || fd >= MAX_OPEN_FILES || open_files[fd][0] == -1) { printf("Invalid file descriptor.\n"); return; } int index = open_files[fd][0]; int pos = open_files[fd][1]; FileControlBlock* fcb = &root_dir[index]; int len = strlen(data); int written = 0; while (written < len) { int block_index = pos / BLOCK_SIZE; int offset = pos % BLOCK_SIZE; if (block_index >= fcb->length) { int new_block = allocate_block(); if (new_block == -1) { printf("Disk full. Cannot write more.\n"); break; } fcb->length++; write_block(new_block, "\0\0\0"); } char buffer[BLOCK_SIZE]; int block = fcb->start_block + block_index; read_block(block, buffer); int space = BLOCK_SIZE - offset; int to_write = (len - written < space) ? len - written : space; memcpy(buffer + offset, data + written, to_write); write_block(block, buffer); written += to_write; pos += to_write; } open_files[fd][1] = pos; printf("Written %d bytes.\n", written); } // 主函数 int main() { init_disk(); init_root_directory(); char line[256], cmd[64]; while (1) { printf("> "); if (!fgets(line, sizeof(line), stdin)) break; sscanf(line, "%s", cmd); if (strcmp(cmd, "login") == 0) { cmd_login(); } else if (strcmp(cmd, "dir") == 0) { cmd_dir(); } else if (strcmp(cmd, "create") == 0) { char filename[64]; sscanf(line, "%*s %s", filename); cmd_create(filename); } else if (strcmp(cmd, "delete") == 0) { char filename[64]; sscanf(line, "%*s %s", filename); cmd_delete(filename); } else if (strcmp(cmd, "open") == 0) { char filename[64]; sscanf(line, "%*s %s", filename); cmd_open(filename); } else if (strcmp(cmd, "close") == 0) { int fd; sscanf(line, "%*s %d", &fd); cmd_close(fd); } else if (strcmp(cmd, "read") == 0) { int fd, size; sscanf(line, "%*s %d %d", &fd, &size); cmd_read(fd, size); } else if (strcmp(cmd, "write") == 0) { int fd; char data[256]; sscanf(line, "%*s %d %[^\n]", &fd, data); cmd_write(fd, data); } else if (strcmp(cmd, "seek") == 0) { int fd, offset; sscanf(line, "%*s %d %d", &fd, &offset); cmd_seek(fd, offset); } else if (strcmp(cmd, "exit") == 0) { break; } else { printf("Unknown command.\n"); } } fclose(disk_file); return 0; } 这段代码的运行结果如下 > login Login successful. > create a.txt File created: a.txt > open a.txt File opened with fd=0 > write 0 1 Written 1 bytes. > read 0 1 Read: > delete a.txt File deleted: a.txt > 请修复代码中的错误
最新发布
05-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值