我正在用c语言(使用openwrt作为操作系统)构建一个项目,将文件上载到FTP服务器。我对传入的数据使用MQTT。因此,对于我订阅的每个主题,我都会保存这些数据,然后将其上载到FTP服务器,为了使事情顺利进行,每次需要上载文件时,我都会使用一个线程来完成这项工作。为了确保程序不会运行太多线程,允许每个主题创建一个线程。我使用了一个变量(比如mutex,但它不是pthread\u mutex\t,因为我不需要阻止线程,我想跳过这一步并上传下一个文件)。我认为使用这种技术我是安全的,但在运行程序15分钟后,我得到了这个错误11,表示当程序尝试创建线程时,资源暂时不可用(pthread\u create)。我试图找出问题的一个方面是。
上载函数(这将创建线程):
void uploadFile(<args...>, bool* locker_p){
*locker_p = true;
args->uploadLocker_p = uploadLocker_p;
<do something here>
pthread_t tid;
int error = pthread_create(&tid, NULL, uploadFileThread, (void*)args);
if(0 != error){
printf("Couldn't run thread,(%d) => %s\n", error, strerror(error));
}
else{
printf("Thread %d\n", tid);
}
}
上载线程:
void *uploadFileThread(void *arg){
typeArgs* args = (typeArgs*)arg;
<do something like upload the file>
*(args->uploadLocker_p) = false;
free(args);
return NULL;
//pthread_exit(0);
}
创建的线程的默认堆栈大小占用了太多的虚拟内存。
本质上,内核是在告诉您的进程,它已经有太多的虚拟内存在使用,它不敢再给它了,因为如果进程突然全部使用,没有足够的RAM和交换来备份它。
要修复,请创建一个属性,将每个线程的堆栈限制为合理的。如果您的线程不使用数组作为局部变量,或者进行深度递归,那么2*PTHREAD_STACK_MIN
(来自
例子:
pthread_attr_t attrs;
pthread_t tid;
int err;
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, 2 * PTHREAD_STACK_MIN);
err = pthread_create(&tid, &attrs, uploadFileThread, (void *)args);
pthread_attr_destroy(&attrs);
if (err) {
/* Failed, errno in err; use strerror(err) */
} else {
/* Succeeded */
}
还要记住,如果您的
上传FileThread()
分配内存,它不会在线程退出时自动释放。看起来OP已经知道这一点(因为他们有函数在准备退出时释放参数结构),但我认为指出它是个好主意。
就我个人而言,我喜欢使用线程池。其想法是,上传工作人员是事先创建的,他们将等待新的作业。以下是一个示例:
pthread_mutex_t workers_lock;
pthread_mutex_t workers_wait;
volatile struct work *workers_work;
volatile int workers_idle;
volatile sig_atomic_t workers_exit = 0;
其中
struct work
是受workers_lock
保护的单链表,workers_idle
在等待新工作时初始化为零并递增,workers_wait
是新工作到达时在workers_lock
下发出信号的条件变量,workers_exit
是一个计数器,当非零时,告诉许多工作人员退出。
一个工人基本上就是
void worker_do(struct work *job)
{
/* Whatever handling a struct job needs ... */
}
void *worker_function(void *payload __attribute__((unused)))
{
/* Grab the lock. */
pthread_mutex_lock(&workers_lock);
/* Job loop. */
while (!workers_exit) {
if (workers_work) {
/* Detach first work in chain. */
struct work *job = workers_work;
workers_work = job->next;
job->next = NULL;
/* Work is done without holding the mutex. */
pthread_mutex_unlock(&workers_lock);
worker_do(job);
pthread_mutex_lock(&workers_lock);
continue;
}
/* We're idle, holding the lock. Wait for new work. */
++workers_idle;
pthread_cond_wait(&workers_wait, &workers_lock);
--workers_idle;
}
/* This worker exits. */
--workers_exit;
pthread_mutex_unlock(&workers_lock);
return NULL;
}
连接处理进程可以使用idle\u workers()
检查空闲工作线程的数量,或者增加工作线程池,或者因为太忙而拒绝连接。空闲的工作者()类似于
static inline int idle_workers(void)
{
int result;
pthread_mutex_lock(&workers_lock);
result = workers_idle;
pthread_mutex_unlock(&workers_lock);
return result;
}
请注意,每个worker只在很短的时间内持有锁,因此调用idle\u workers()不会阻塞很长时间。(pthread\u cond\u wait()
在开始等待信号时自动释放锁,并且仅在重新获取锁后返回。)
在接受中等待新连接时,请将套接字设置为非阻塞,并使用轮询等待新连接。如果超时时间已过,请检查工作人员的数量,如有必要,请调用reduce\u workers(1)或类似命令来减少工作人员的数量:
void reduce_workers(int number)
{
pthread_mutex_lock(&workers_lock);
if (workers_exit < number) {
workers_exit = number;
pthread_cond_broadcast(&workers_wait);
}
pthread_mutex_unlock(&workers_lock);
}
为了避免为每个线程调用pthread\u join(),我们甚至不知道这里有哪些线程退出要获取/释放与线程相关的内核和C库元数据,需要分离工作线程。成功创建工作线程tid后,只需调用pthread\u detach(tid) 。
当新连接到达并且确定应该委托给工作线程时,您可以(但不必)检查空闲线程的数量、创建新的工作线程、拒绝上载或只是将工作附加到队列中,以便“最终”处理它。
以下是错误日志: 这里有一个相关的问题:https://stackoverflow.com/a/14370767,它建议使用SO_SNDTIMEO套接字选项设置发送超时。
我在C中使用tcp套接字服务器和客户端。使用AF_INET、SOCK_STREAM和IPPROTO_TCP 在sock send()命令上有一个可能导致“资源暂时不可用”的帖子,其中Davide Berra说 这是因为您使用的是非阻塞套接字,并且输出缓冲区已满。 从send()手册页
假定套接字处于阻塞模式
创建套接字 使其非阻塞 呼叫连接 按预期返回-1和errno EINPROGRESS 调用select 返回>0,因此已建立连接 再次阻塞套接字 此部件的代码如下: 那还行。但是我有一个循环,在这个循环中我调用了一个函数,该函数检查是否收到了要读取的新数据包:
我有一个伪终端从机,它给我一个资源暂时不可用的读/写错误(11)。我一直无法解决这个问题,但直到一周前我还不知道任何事情。所以,我可能漏掉了一些明显的东西。 根据我所了解的情况,这可能是由对非阻塞PTY调用引起的。但是,当我检查从pty的I之后的时,该值显示它是一个阻塞文件描述符。 我甚至尝试将视为非阻塞文件,使用来确定它何时就绪。但是,它只是每次都超时。 那么,如果设置为blocking,为什么
本文向大家介绍Ubuntu E: 无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用),包括了Ubuntu E: 无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用)的使用技巧和注意事项,需要的朋友参考一下 Ubuntu 18.04,其他版的Ubuntu也一样 问题: 当运行sudo a