理解原子操作

操作系统
Published

May 19, 2018

题目

 编写一个程序,最多可接收3个命令行参数:

$ ./5-3 filename num-bytes [-x]

该程序打开指定的文件,然后每次写入一个字节的方式,向尾部追加num-bytes字节。缺省情况下,打开文件的标志应有O_APPEND,但若存在第三个命令行参数,那么就使用lseek到文件末尾再进行写入。最后运行这两个命令查看结果:

./5-3 f1 1000000  & ./5-3 f1 1000000 

./5-3 f1 1000000 -x & ./5-3 f1 1000000 -x

代码

#include <ctype.h>
#include "tlpi_hdr.h"
#include <stdbool.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
    char ch;
    char byte='a';
    bool x = FALSE;
    int fd=-1,cnt;
    /* 读取选项 */
    if (argc < 3)
    {
        usageErr("filename num-bytes [-x]\n");
        exit(EXIT_SUCCESS);
    }
    while ((ch = getopt(argc, argv, "x")) != -1)
    {
        switch (ch)
        {
        case 'x':
            printf("have x\n");
            x = TRUE;
            break;
        default:
            usageErr("filename num-bytes [-x]\n");
            break;
        }
    }
    
    if (x)//有x的情况
    {
        //当判断到了-x后,参数会被重新排列
        cnt=atoi(argv[3]);
        byte='x';
        //改成lseek来调整
        fd=open(argv[2],O_RDWR | O_CREAT , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
        if(fd==-1)
        {
            errExit("open");
        }
        while(cnt)
        {
            lseek(fd,0,SEEK_END);
            write(fd,&byte,1);
            cnt--;
        }   
    }else
    {   
        cnt=atoi(argv[2]);
        //只写 追加 证明了O_APPEND是原子操作,使用时不会受多线程的影响
        fd=open(argv[1],O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
        if(fd==-1)
        {
            errExit("open");
        }
        while(cnt)
        {
             write(fd,&byte,1);
            cnt--;
        }
    }

    exit(EXIT_SUCCESS);
}

结果

  • 不带-x参数 sh $ ./5-3 f1 1000000 & ./5-3 f1 1000000 $ ls -lh f1 -rw-rw-r-- 1 zqh zqh 2.0M 5月 9 10:38 f1

  • 带-x参数

    $ ./5-3 f1 1000000 -x & ./5-3 f1 1000000 -x
    $ ls -lh f1
    -rw-rw-r-- 1 zqh zqh 1010K 5月   9 10:46 f1
  • 总结

     使用O_APPEND参数打开的文件属于原子操作,两个不同的进程对一个文件做输入,是不可分割的操作  使用lseek操作,不属于原子操作。

扩展

 我尝试修改了这个程序名为5-3.1,并且查看结果 | | 原程序 | 新程序 | |– |———-|———-| |无 -x |写入a |写入b | |有 -x |写入x |写入y |

  • 不带-x参数