草庐IT

c - write() 在两种情况下表现不同

coder 2023-06-22 原文

所以我被要求解决这个练习:

此练习旨在演示为什么需要使用 O_APPEND 标志打开文件来保证原子性。编写一个最多接受三个命令行参数的程序:

$ atomic_append filename num-bytes [x] 

此文件应打开指定的文件名(如有必要则创建它)并使用 write() 在文件中写入一个字节,将 num-bytes 字节追加到文件中时间。默认情况下,程序应使用 O_APPEND 标志打开文件,但如果提供了第三个命令行参数 (x),则应省略 O_APPEND 标志,相反,程序应该在每个 write() 之前执行一个 lseek(fd, 0, SEEK_END) 调用。在不使用 x 参数的情况下同时运行该程序的两个实例以将 100 万字节写入同一文件:

$ atomic_append f1 1000000 & atomic_append f1 1000000 

重复相同的步骤,写入不同的文件,但这次指定 x 参数:

$ atomic_append f2 1000000 x & atomic_append f2 1000000 x 

使用 ls –l 列出文件 f1 和 f2 的大小并解释差异。

这就是我写的:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {
        int fd, flags, num_bytes;
        if (argc < 3 || strcmp(argv[1], "--help") == 0) {
                printf("Usage: %s filename num-bytes [x]\n", argv[0]);
                return 1;
        }
        num_bytes = atoi(argv[2]);
        if (argc == 4 && strcmp(argv[3], "x") == 0) {
                fd = open(argv[1], O_CREAT | O_WRONLY, 0666);
                if (fd == -1)
                        perror("open");
                while (num_bytes-- > 0) {
                        lseek(fd, 0, SEEK_END);
                        write(fd, "a", 1);
                }
                if (close(fd) == -1)
                        perror("close");
        }
        else {
                fd = open(argv[1], O_CREAT | O_APPEND | O_WRONLY, 0666);
                if (fd == -1)
                        perror("open");
                while(num_bytes-- > 0)
                        write(fd, "a", 1);
                if (close(fd) == -1)
                        perror("close");
        }
        return 0;
}

在我按要求运行之后:

abhinav@cr33p:~/System/5$ ./a.out f1 1000000 & ./a.out f1 1000000
[1] 4335
[1]+  Done                    ./a.out f1 1000000
abhinav@cr33p:~/System/5$ ./a.out f2 1000000 x & ./a.out f2 1000000 x
[1] 4352
[1]+  Done                    ./a.out f2 1000000 x
abhinav@cr33p:~/System/5$ ls f1 f2
f1  f2
abhinav@cr33p:~/System/5$ ls -l f*
-rw-rw-r-- 1 abhinav abhinav 2000000 Dec 10 16:23 f1
-rw-rw-r-- 1 abhinav abhinav 1000593 Dec 10 16:24 f2

当然,文件大小有差异我有点无法清楚地理解为什么?我搜索并在某个地方找到了这个解释:

The sizes were definitely different:

-rw------- 1 posborne posborne 1272426 2012-01-15 21:31 test2.txt
-rw------- 1 posborne posborne 2000000 2012-01-15 21:29 test.txt

Where test2.txt was run without O_APPEND. test2.txt is short by the number of times (or bytes as a result of times) that seeking to the end of the file did not happen at the same time as the write (quite frequently).

但似乎没有任何意义。那么为什么大小不同?

最佳答案

此代码,在未使用 O_APPEND 打开的文件上运行:

            while (num_bytes-- > 0) {
                    lseek(fd, 0, SEEK_END);
                    write(fd, "a", 1);

写入 文件末尾的位置,就像调用 lseek() 时一样。文件结尾可能会在 lseek()write() 调用之间发生变化。

此代码,在使用 O_APPEND 打开的文件上:

            while(num_bytes-- > 0)
                    write(fd, "a", 1);

保证 write()'ing 到用O_APPEND 打开的文件以写入文件末尾的标准行为无论那一端在哪里

这就是 O_APPEND 标志的全部要点 - lseek() 然后 write() 不起作用.

关于c - write() 在两种情况下表现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41074861/

有关c - write() 在两种情况下表现不同的更多相关文章

  1. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  2. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  3. ruby - 在不使用 RVM 的情况下在 Mac 上卸载和升级 Ruby - 2

    我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案

  4. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

  5. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

    RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

  6. ruby - 在什么情况下会使用 Sinatra 或 Merb? - 2

    我正在学习Rails,对Sinatra和Merb知之甚少。我想知道您会在哪些情况下使用Merb/Sinatra。感谢您的反馈! 最佳答案 Sinatra是一个比Rails更小、更轻的框架。如果你想让一些东西快速运行,只需发送几个URL并返回一些简单的内容,就可以使用它。看看Sinatrahomepage;这就是启动和运行“Hello,World”所需的全部内容,而在Rails中,您需要生成整个项目结构、设置Controller和View、设置路由等等(我还没有有一段时间写了一个Rails应用程序,所以我不知道“Hello,World

  7. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  8. ruby-on-rails - 在这种情况下我如何模拟一个对象?没有明显的方法可以用模拟替换对象 - 2

    假设我在Store的模型中有这个非常简单的方法:defgeocode_addressloc=Store.geocode(address)self.lat=loc.latself.lng=loc.lngend如果我想编写一些不受地理编码服务影响的测试脚本,这些脚本可能已关闭、有限制或取决于我的互联网连接,我该如何模拟地理编码服务?如果我可以将地理编码对象传递到该方法中,那将很容易,但我不知道在这种情况下该怎么做。谢谢!特里斯坦 最佳答案 使用内置模拟和stub的rspecs,你可以做这样的事情:setupdo@subject=MyCl

  9. ruby - 在没有基准或时间的情况下用 Ruby 测量用户时间或系统时间 - 2

    因为我现在正在做一些时间测量,我想知道是否可以在不使用Benchmark类或命令行实用程序time的情况下测量用户时间或系统时间。使用Time类只显示挂钟时间,而不显示系统和用户时间,但是我正在寻找具有相同灵active的解决方案,例如time=TimeUtility.now#somecodeuser,system,real=TimeUtility.now-time原因是我有点不喜欢Benchmark,因为它不能只返回数字(编辑:我错了-它可以。请参阅下面的答案。)。当然,我可以解析输出,但感觉不对。*NIX系统的time实用程序也应该可以解决我的问题,但我想知道是否已经在Ruby中实

  10. ruby - 如何更优雅地记下这三种情况? - 2

    是否可以让这段代码更紧凑?我在这里错过了什么吗?ifvaluemax_ratemax_rateelsevalueend 最佳答案 这里有一些完全不同的东西:[min_rate,value,max_rate].sort[1] 关于ruby-如何更优雅地记下这三种情况?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/13309740/

随机推荐