这是一个令人尴尬的简单问题,但我似乎无法使用文件描述符打开一个新文件进行写入。我尝试过的每一个变体都会返回-1。我缺少什么?这就是使用文件描述符初始化文件的方式,对吗?我找不到另有说明的文档。
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
fd = open ("/home/CSTCIS/sample.dat", O_WRONLY, mode);
printf("%d\n", fd);
}
Run Code Online (Sandbox Code Playgroud)
perror() 打印open: No such file or directory。
考虑以下示例,模拟一个在 10 秒后给出输出的命令:exec 5< <(sleep 10; pwd)
在 Solaris 中,如果我在 10 秒之前检查文件描述符,我可以看到它的大小为 0,这告诉我它尚未填充数据。我可以简单地每秒检查一次,直到满足文件测试条件(不同于 0),然后提取数据:
while true; do
if [[ -s /proc/$$/fd/5 ]]; then
variable=$(cat <&5)
break
fi
sleep 1
done
Run Code Online (Sandbox Code Playgroud)
但在 Linux 中我不能这样做(RedHat、Debian 等)。所有文件描述符都以 64 字节大小显示,无论它们是否保存数据。对于需要不同时间来转储输出的各种命令,我不知道何时应该读取文件描述符。不,我不想只是等待cat <&5完成,我需要知道什么时候应该cat首先执行。因为我使用这种机制来发出同时命令并将其输出分配给相应的文件描述符。正如已经提到的,这在 Solaris 中效果很好。
是否可以通过系统调用知道write(2)我要发送数据的 fd 是打开还是关闭?
我的问题是我正在写入一个有时关闭有时打开的文件描述符。我想一定有办法知道write这种情况,但我找不到。
我们在 Tomcat 上部署了一个 Web 应用程序,它可以有超过 300k 的文件描述符,而我们对单个进程的限制是 250k。奇怪的是:当服务器运行时,数字会上升(400k)和下降(100k)。有时,当数字很高时,我们无法 ssh 进入操作系统。但是,我们没有发现任何与许多打开文件或套接字建立问题相关的错误。大多数文件描述符与 JVM 加载的 jar 文件相关。我的问题是:
1.操作系统(CentOS 7)如何计算tomcat的文件描述符?我认为 Tomcat 在运行时不会保持这些文件打开。2、为什么数量不固定?相反,有很多重复的 jar 文件。3. 这么多文件描述符正常吗?
据我所知,在调用 fork() 后,子进程继承其父进程的每进程文件描述符表(指向相同的系统范围打开文件表)。因此,当在父进程中打开文件然后调用 fork() 时,子进程和父进程都可以写入该文件,而不会覆盖彼此的输出(由于打开文件表条目中的共享偏移量)。
但是,假设我们在分叉后(在父级和子级中)对某个文件调用 open() 。这是否会在系统范围的打开文件表中创建一个单独的条目,并为子进程提供一组单独的偏移量和读写权限标志(尽管它在技术上是同一个文件)?我尝试过查找这个问题,但似乎无法找到明确的答案。
我问这个主要是因为我正在尝试写入文件,并且在上述情况下,似乎只有父级和子级的输出最终出现在文件中。这似乎意味着打开文件表中有两个单独的打开调用的单独条目,因此有单独的偏移量,因此较慢的进程会覆盖另一个进程的输出。
为了说明这一点,请考虑以下代码:
int main(void) {
int fd;
if(!fork()) {
/* child */
fd = open("output", O_CREAT|O_TRUNC|O_WRONLY, 0666);
write(fd, "hello ", 6);
_exit(0);
} else {
fd = open("output", O_CREAT|O_TRUNC|O_WRONLY, 0666);
write(fd, "world\n", 6);
}
}
Run Code Online (Sandbox Code Playgroud)
这只会打印“hello”或“world”之一。相反,如果我们在分叉之前调用 open() (并在之后删除两个 open 调用),我们将看到“hello world”(或可能是“world”) hello"),这是有道理的。那么系统打开文件表中是否有两个不同的条目?
我根据我对文件描述符重定向的理解在 bash 上做了一些测试,发现:
((echo STDOUT; echo STDERR >&2;) 3>&1 1>&2 2>&3 3>&-) 2> /dev/null
Run Code Online (Sandbox Code Playgroud)
和
(echo STDOUT; echo STDERR >&2;) 3>&1 1>&2 2>&3 3>&- 2> /dev/null
Run Code Online (Sandbox Code Playgroud)
给出了不同的结果。第一个给出了自和fds 交换STDERR以来的预期输出,但第二个给出了意外输出,就好像 fds 从未交换过一样。stdoutstderrSTDOUT
这对我来说是令人惊讶的。在这种情况下,我不知道额外的括号会做什么来改变输出。使用大括号也有同样的效果。
所以我认为的“预期”结果实际上是错误的,因为我错误地想象了正在发生的事情。实际发生的情况是( -> 的左侧是文件描述符(或者在最后一列的情况下是命令),右侧是底层文件句柄将输出到的位置):
1 -> stdout 1 -. ,-> stdout 1 -. ,-> /dev/null echo STDOUT -> stderr
X X
2 -> stderr 2 -' '-> stderr 2 -' '-> stderr echo STDERR >&2 -> /dev/null
Run Code Online (Sandbox Code Playgroud)
经过@JohnKugelman 的解释,现在这是有道理的。
1 -> stdout 1 -> …Run Code Online (Sandbox Code Playgroud) 我想测试 引用的给定文件的位置是否fd位于文件末尾。例如 当前位置==文件大小。有没有办法在少于 3 个系统调用的情况下完成此操作?这 3 个调用是:
lseeklseek到文件末尾并存储该位置(即文件大小)lseek则回到原来的位置。文件描述符可以使用UNIX域套接字在同一主机上从一个进程传递到另一个进程.有人可以告诉你是否有办法在不同主机上的进程之间传递文件描述符?
我正在开发一个备份实用程序,我收到错误:
系统中打开的文件太多
运行一段时间后.错误由返回stat().
由于我实际上没有打开任何文件(fopen()),我的问题是,如果以下任何函数(我正在使用)占用文件描述符,如果是这样,我该怎么做才能释放它?
getwd()chdir()mkdir()stat()time()tl; dr是否有我可以放入的posix描述符值,close()什么也不会发生?
有没有可以NULL用于指针,文件描述符的特定值?我希望代码是统一的,所以我认为我可以将源描述符设置为空描述符。
class socket
{
int fd;
public:
//deleted copy operations
socket(socket&& other):
fd{other.fd}
{
other.fd = /*null descriptor*/
}
~socket()
{
if (close(fd) == -1)
{
throw std::runtime_error{strerror(errno)};
}
// ^^ null file descriptor will do nothing on close()
// like delete nullptr;
}
Run Code Online (Sandbox Code Playgroud)
我可以存储一个布尔型标志,但是我想避免它。
它将使用的操作系统是带有gcc 5.4的Ubuntu 16.04。我不能使用POSIX和标准库本身以外的任何库,直到gcc 5.4中存在的版本为止。
我试图阅读手册页open(),close()。他们没有提及要使用的任何特殊价值。
我尝试将其设置为-1,但不确定在所有地方使用是否安全。