open多次调用出现 EAGAIN错误

本文通过一个简单的代码示例,探讨了SystemVIPC标识符与文件标识符的区别,以及在使用open函数访问文件时,返回的文件标识符是否一致。实验中遇到了POSIX EAGAIN错误,揭示了该错误在非阻塞操作和资源暂时不可用情况下的含义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在看到说System V IPC的标识符是处于整个系统中的。并不是局限于单个进程中。书上说文件标识符是存在于进程中的,就想来验证一下,同时用open函数访问某个文件的时候,返回的文件标示符是否是一样的。
写了一个很简单的代码如下:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>


int main(int argc, char const *argv[])
{
	int fd = open("/Users/yannie/Desktop/1.txt",O_RDWR | 0644);
	if(fd < 0)
		perror("open");
	printf("%d\n", fd);
	sleep(10);
	return 0;
}

不巧,却发现了这个错误:
EAGAIN
POSIX EAGAIN {resource temporarily unavailable}
从字面上来看,是提示再试一次。这个错误经常出现在当应用程序进行一些非阻塞(non-blocking)操作(对文件或socket)的时候。例如,以 O_NONBLOCK的标志打开文件/socket/FIFO,如果你连续做read操作而没有数据可读,此时程序不会阻塞起来等待数据准备就绪返回,read函数会返回一个错误EAGAIN,提示你的应用程序现在没有数据可读请稍后再试。
  又例如,当一个系统调用(比如fork)因为没有足够的资源(比如虚拟内存)而执行失败,返回EAGAIN提示其再调用一次(也许下次就能成功)。

如果你不想使用OpenCV这样的库,而仅想使用标准的C库来操作Linux摄像头,那么你可以依赖于系统的视频输入设备驱动,比如`video4linux2` (V4L2)。以下是一个简化版的例子,展示如何基本地打开摄像头并获取单张图片(不包括实时流): 1. 打开摄像头设备文件: ```c int fd = open("/dev/video0", O_RDWR); // 替换为实际的摄像头设备文件名 if (fd < 0) { perror("Error opening camera device"); return -1; } ``` 2. 设置相机参数(如果需要): ```c struct v4l2_format fmt; memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = 640; // 指定宽度 fmt.fmt.pix.height = 480; // 指定高度 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; // 图像格式 if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) { perror("Failed to set image format"); close(fd); return -1; } ``` 3. 获取一帧数据: 首先,创建一个足够大的缓存区域来存储图像数据,然后使用`mmap()`将该区域映射到内存上,并通过`ioctl()`请求一帧数据: ```c struct v4l2_buffer buffer; buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) { perror("Failed to query buffer info"); close(fd); return -1; } char* img_data = (char*)malloc(buffer.length); if (!img_data) { perror("Memory allocation failed"); close(fd); return -1; } if (ioctl(fd, VIDIOC prefetch, &buffer) != 0) { perror("Failed to prefetch buffer"); free(img_data); close(fd); return -1; } if (ioctl(fd, VIDIOC_DQBUF, &buffer) == -EAGAIN) { printf("No new frames available\n"); close(fd); free(img_data); return -1; } // 现在img_data指向了一帧数据 ``` 4. 解析和保存图像数据: 将接收到的数据解码成实际的图像数据格式,这可能会因设备和格式的不同而有所变化。假设是YUV格式,可以按行读取数据并组合成RGB或其他所需的格式,然后保存到硬盘或者其他地方。 5. 清理资源: ```c munmap(img_data, buffer.length); ioctl(fd, VIDIOC_QBUF, &buffer); // 返回缓冲区给内核 close(fd); free(img_data); ``` 注意:这个例子仅适用于一次性获取一张静态图片。若要实现连续捕捉和处理视频流,你需要处理更多的细节,如使用循环、错误处理、缓冲区管理以及图像解码等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五月的天气

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值