今天我不得不使用这个basename()功能,而man 3 basename(这里)给了我一些奇怪的信息:
笔记
有两个不同版本的basename() - 上面描述的POSIX版本,以及GNU版本,后者可以使用
#define _GNU_SOURCE
#include <string.h>
我想知道这#define _GNU_SOURCE意味着什么:它是否污染了我用GNU相关许可证编写的代码?或者它只是用于告诉编译器类似" 嗯,我知道,这组函数不是POSIX,因此不可移植,但我还是想用它 ".
如果是这样,为什么不给人们不同的标题,而不是必须定义一些模糊的宏来获得一个函数实现或另一个?
有些东西也让我感到困惑:编译器如何知道哪个函数实现与可执行文件链接?它也使用这个#define吗?
有人有一些指示可以给我吗?
TL; DR:如果Linux内核丢失了缓冲的I/O写入,那么应用程序是否有任何方法可以找到?
我知道你有fsync()文件(和它的父目录)的耐用性.问题是,如果内核由于I/O错误而丢失了待写入的脏缓冲区,应用程序如何检测并恢复或中止?
想想数据库应用程序等,其中写入顺序和写入持久性可能是至关重要的.
Linux内核的模块层可以在某些情况下失去缓冲已成功提交的I/O请求write(),pwrite()等等,有这样的错误:
Buffer I/O error on device dm-0, logical block 12345
lost page write due to I/O error on dm-0
Run Code Online (Sandbox Code Playgroud)
(见end_buffer_write_sync(...)和end_buffer_async_write(...)在fs/buffer.c).
Buffer I/O error on dev dm-0, logical block 12345, lost async page write
Run Code Online (Sandbox Code Playgroud)
由于应用程序write()已经无错误地返回,因此似乎无法将错误报告给应用程序.
我不熟悉内核源代码,但我认为它设置AS_EIO在缓冲区上,如果它正在执行异步写入,则无法写出:
set_bit(AS_EIO, &page->mapping->flags);
set_buffer_write_io_error(bh);
clear_buffer_uptodate(bh);
SetPageError(page);
Run Code Online (Sandbox Code Playgroud)
但是我不清楚应用程序是否或如何在以后查找fsync()文件以确认它在磁盘上时会发现这一点.
我正要为我们这里的应用程序添加一个额外的信号处理程序,我注意到作者已经习惯sigaction()了设置其他信号处理程序.我打算用signal().按照惯例我应该使用,sigaction()但如果我是从头开始写,我应该选择哪个?
我编写了一个程序,用于将其输出打印到stdout的赋值.赋值规范要求创建一个Makefile,在调用make run > outputFile时应运行程序并将输出写入文件,该文件的SHA1指纹与规范中给出的指纹相同.
我的问题是我的makefile:
...
run:
java myprogram
Run Code Online (Sandbox Code Playgroud)
还会将运行我的程序的命令(例如java myprogram)输出到输出文件,这样我的文件就会包含这个额外的行,导致指纹错误.
有没有办法在没有命令调用回显到命令行的情况下执行命令?
一般来说,当我们从多个进程附加到UNIX中的文件时,我们可以理所当然地认为什么?是否有可能丢失数据(一个进程会覆盖其他进程)?数据是否可能被破坏?(例如,每个进程在每个追加到日志文件时附加一行,是否有可能两行被破坏?)如果追加在上述意义上不是原子的,那么确保互斥的最佳方法是什么?
在POSIX系统上,终止信号通常具有以下顺序(根据许多MAN页面和POSIX规范):
SIGTERM - 礼貌地要求进程终止.它将正常终止,清理所有资源(文件,套接字,子进程等),删除临时文件等.
SIGQUIT - 更有力的请求.它应该终止不正常,仍然清理绝对需要清理的资源,但可能不会删除临时文件,可能会在某处写入调试信息; 在某些系统上也会写入核心转储(无论信号是否被应用程序捕获).
SIGKILL - 最有力的要求.甚至没有要求该过程做任何事情,但系统将清理过程,无论是否喜欢.最有可能是编写核心转储.
SIGINT如何适应这张照片?当用户点击CRTL + C时,CLI进程通常由SIGINT终止,但是后台进程也可以由SIGINT使用KILL实用程序终止.我在规范或头文件中看不到的是SIGINT是否比SIGTERM更强或更强,或者SIGINT和SIGTERM之间有任何区别.
更新:
到目前为止,我发现的终止信号的最佳描述是在GNU LibC文档中.它很好地解释了SIGTERM和SIGQUIT之间存在预期的区别.
它说关于SIGTERM:
这是礼貌地要求程序终止的正常方式.
它说关于SIGQUIT:
[...]并在终止进程时生成核心转储,就像程序错误信号一样.您可以将此视为用户"检测到"的程序错误情况.[...]在处理SIGQUIT时最好省略某些类型的清理.例如,如果程序创建临时文件,它应该通过删除临时文件来处理其他终止请求.但是SIGQUIT最好不要删除它们,以便用户可以与核心转储一起检查它们.
而SIGHUP也解释得很好.SIGHUP实际上不是终止信号,它只是意味着用户的"连接"已经丢失,因此应用程序不能指望用户读取任何进一步的输出(例如stdout/stderr输出),并且没有输入可以从用户不再.对于大多数意味着他们退出的应用程序.从理论上讲,应用程序还可以决定在收到SIGHUP时进入守护进程模式,现在作为后台进程运行,将输出写入已配置的日志文件.对于已经在后台运行的大多数守护进程,SIGHUP通常意味着他们将重新检查其配置文件,因此您在编辑配置文件后将其发送到后台进程.
但是,除了CRTL + C发送的SIGINT之外,此页面上没有有用的SIGINT解释.是否有理由以不同于SIGTERM的方式处理SIGINT?如果是这样,那将是什么原因以及如何处理不同?
网页上散布着各种描述POSIX AIO设施的页面,其中包含不同的细节.它们都不是最近的.目前还不清楚他们究竟在描述什么.例如,Linux内核异步I/O支持的"官方"(?)网站说套接字不起作用,但我的Ubuntu 8.04.1工作站上的"aio.h"手册页似乎都暗示它适用于任意文件描述符.然后还有另一个项目似乎在图书馆层工作,文档更少.
我想知道:
<aio.h>似乎有希望?我可以使用的其他多路复用机制非常好,但随处可见的信息碎片让我很好奇.
根据我的理解,SIGPIPE只能作为a的结果发生write(),它可以(并且确实)返回-1并设置errno为EPIPE......那么为什么我们有额外的信号开销?我每次使用管道时都会忽略SIGPIPE并且从未感到任何痛苦,我是否遗漏了什么?
我基本上是在寻找fdopen()的C++版本.我对此做了一些研究,这似乎应该是容易的事情之一,但事实证明是非常复杂的.我是否遗漏了这种信念(即它真的很容易)?如果没有,是否有一个好的图书馆在那里处理这个?
编辑:将我的示例解决方案移到单独的答案.