原子操作 同步

1.原子操作

原子:不可分割的最小单位

原子操作的作用就是解决竞争和冲突

前面我们说的临时文件有一个函数tmpnam不够安全,它不够安全的原因就是不够原子。没有办法将创建名字与打开文件这两部分合二为一。

程序中的重定向:dup,dup2。

/*#include "main.h"
int main()
{
        //在不修改下面的代码实现将hello输出到我们想输出的文件里面去
        printf("hello world !");
        exit(0);
}*/
/*方法:printf输出到文件描述符为1,它只认识这个1并不认识其他的
 *而文件描述符又默认使用最小的 所以我们只需要关闭1,打开你想输入进去的文件
 *就可以达到输入到某一个文件中去。
 * */
#include "main.h"
#define PATHNAME "/tmp/out"
int main()
{
        int fd;
        close(1);
        fd=open(PATHNAME,O_WRONLY|O_CREAT|O_TRUNC,0666);
        if(fd<0)
        {
                perror("open()");
                exit(1);
        }
        printf("hello world!");
        exit(0);
}
/*这种方法还是不行因为你关闭了1,但是其他进程可以在你关闭1还没有打开其他文件
 *的时候,打开了一个文件,这样你就会输出到其他文件里面去了
 * 还是不够原子
 * */
int dup(int oldfd);复制一个文件描述符到最小的文件描述符。

/*方法二实现输出重定向*/
#include "main.h"
#define PATHNAME "/tmp/out"
int main()
{
    int fd;
    fd=open(PATHNAME,O_WRONLY|O_CREAT|O_TRUNC,0666);
    if(fd==1)
            exit(1);
    close(1);
    dup(fd);
    close(fd);
    printf("hello world");
    exit(0);
}
但是这个函数是由bug的,比如你再关闭1后在你还没有实现dup时,打开了一个文件,那么就会占用1号文件描述符。原因还是close和duo不够原子。

int dup2(int oldfd,int newfd);可以将这两部合成一部。

让newfd称为oldfd的一个副本,如果newfd存在,那么关闭、如果oldfd和newfd是同一个那么就do nothing 然后返回oldfd。

#include "main.h"
#define PATHNAME "/tmp/out"
int main()
{
        int fd;
        fd=open(PATHNAME,O_WRONLY|O_CREAT|O_TRUNC,0666);
        dup2(fd,1);
        printf("hello world!");
        exit(0);
}
/*这个程序是有bug的。我们在写程序的时候应该注意以下几点1.不能发生内存泄漏2.不能写越界
 * 3.我们在写程序的不能当作自己一个人在写,应该当作模块在写,进函数时的状态是什么样,那么出函数的状态就应该是什么样。
 * 这个函数进来时候的状态是1为stdout但是出去的时候这个函数的状态为1为其他文件的描述符。
 * */
#include "main.h"
#define PATHNAME "/tmp/out"
int main()
{
        int fd;
        int stdout_copy=1;
        int ret=1;
        fd=open(PATHNAME,O_RDWR|O_CREAT|O_TRUNC,0666);
    //    printf("\n");
        if(fd<0)
        {
                perror("open()");
                exit(1);
        }
        //printf("\n");
        stdout_copy=dup(1);
    //    printf("\n");
        if(stdout_copy<0)
        {
                perror("dup()");
                exit(1);
        }
        printf("\n");
        ret=dup2(fd,1);
        if(ret<0)
        {
                perror("dup2()");
                exit(1);
        }
        printf("hello world\n");
        ret=dup2(stdout_copy,1);
        if(ret<0)
        {
                perror("dup2()");
                exit(1);
        }
        printf("hello world!\n");
        close(stdout_copy);
        close(fd);
        exit(0);
}
注意这个程序里面的printf("\n");是必须要了否则无法实现一个输出在终端,一个输出在文件里面。

有些pirntf();前面有//表示printf()放在那个位置也行。

下面也是一种实现

    int fd=open("test.txt",O_RDWR|O_CREAT);
    printf("\n");        //回车不可少。只有按下回车后,数据才被送往键盘缓冲区,形成输入流
    int stdout_cp=100;    //先用dup2(...)函数复制stdout文件描述符1,然后复制回去
    dup2(1,stdout_cp);
    close(1);            //关闭stdout
    int fd2=dup(fd);    //dup会复制fd文件描述符到当前未打开的最小描述符,即1
    printf(.....);        //printf输出的内容直接输入文件描述符fd指向的文件,即test.txt
    close(fd2);            //等于close(1)
    dup2(stdout_cp,1);    //把指向stdout的文件描述符复制回去
    printf(.....);        //又可以向屏幕输出了
 

2.同步

sync同步buffer(cache内核层次实现)

void  sync(void);

全局催促,在关机的时候也就是解除设备挂载的时候。在即将解除设备挂载的时候,将buffer和cache中还没有来得及同步的数据进行刷新一下。

int fsync(int fd);

同步指定一个文件的buffer或者cache。

int fdatasync(int fd);只刷新数据不刷新亚数据。

数据是指一个文件中有效内容,亚数据是文件属性,文件最后修改的时间。

fcnt();文件描述符所变的魔术几乎都来源与该函数。

int fcntl(int fd,int cmd,..../*arg*/);

函数的五种功能:

 1.复制一个现有的描述符(cmd=F_DUPFD).

         2.获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD).

            3.获得/设置文件状态标记(cmd=F_GETFL或F_SETFL).

            4.获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN).

            5.获得/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW).

文件描述符要做什么命令,是否要传参,以及要传上面参。

因为命令不同,可传的参数不同,因为命令不同,返回的值也不同。

ioctl();设备相关的内容都归它管。

一切皆文件的设计原理好不好

简化绝大多数人的操作,总共有五个操作,open,close,read,write,,lseek.

但是对小部分人不好,那些专门跟设备打交道的人。

int ioctl(int fd, unsigned long request, ...);

一个fd(也就device)要做上面requst,要传上面参数。

/dec/fd目录:是一个虚目录,显示当前进程文件描述符信息,谁看显示谁。

使用ls -l /dev/fd/,看到的是实现ls命令所用到的文件描述符信息。

看某一进程,那么就在进程中打开这个目录,得到用到的文件名描述符。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小白羊羊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值