Linux学习第五天

一、昨日回顾

1、在C语言中得到文件的当前目录使用命令getcwd(NULL,0)

2、如何得到当前的文件名?DIR*dir=opendir(目录名)

3、在C语言中改变当前目录chdir("/tmp")

4、超级块信息dirent/文件节点信息inode/文件内容

5、改变文件大小使用函数ftruncate(fd,size)

 

二、上午的内容

1、VIM-plus安装

(1)安装,使用群里下载好的安装包,复制到Ubuntu下,使用命令tar -xvf 进行解压缩,然后使用命令./install.sh进行安装

(2)安装了vim-plus后怎么关闭

改变./vimrc文件的文件名,mv vimrc backup_vimrc

 

2、X-shell死机后,文件怎么办?

再次重启机器后,再次打开该文件,可以看到该文件的backup,这时可以选择是否要恢复文件

 

3、mmap的其他功能?

(1)mmap(viod *addr,size_t length,int prot,int flags,int fd,pff_t offset)

(2)使用munmap命令解除映射,要解除就要全部解除

(3)练习mmap的例子

(4)练习munmmap的例子

(5)Linux的一个物理页的大小是4k

(6)touch file1创建一个大小为0的空文件

使用strcpy(p,"how")实际拷贝的是4个字符

使用Strncpy(p,"how")实际拷贝的是3个字符

(7)映射内存的例子

 

4、lseek

使用文件定位函数lseek,可以制造文件空洞,文件空洞服务于mmap

 

 

5、获取文件信息

可以通过各种宏去获取一些文件信息,在第12页,例如S_ISDIR、S_ISREG、S_ISLNK等函数

 

6、fopen与open的关系

 

Fopen(argv[1],"ab+");----此命令使用与fp

Open(argv[1],O_RDER);---此命令适用于fd

判断打开成功还是失败?使用ERROR_CHECK

 

7、如何通过fp得到fd?

使用fileno函数,将fp放进去,就可以得到对应的文件描述符

例如:int fd=fileno(fp);

 

8、fread的效率高还是read效率高?二者的区别在哪里?

要看具体的使用场景

 

9、fdopen函数:fdopen(int fd,const char *type)

有些特殊文件不能用io打开,因此我们需要先使用open函数获取文件的文件描述符fd,这也是fdopen的第一个参数,第二个参数是常量,不同的类型有不同的意义

 

 

10、要注意fp和fd的区别

如果是通过fd生成的fp,那么直接用fclose关闭fp就可以,如果先关闭了fd,那么fp就成了一个空指针

 

 

11、第13页,文件描述符的复制

复制使用系统调用dup进行

int fd,fd1;

fd=open(argv[1],O_RDWR);

fd1=dup(fd);

 

(1)直接int fd,fd1,令fd1=fd

①可以实现复制吗?答案是不可以

②怎样就可以复制了?将fd1=fd,改为fd1=dup(fd);

(2)fd是文件描述符
(3)通过dup可以实现重定向标准输出

(4)想要两个文件描述符,不一样,但是指向一个文件,怎么操作?使用两次open命令,打开两次该文件即可

练习例子:

 

 

 

 

(5)为什么使用dup复制文件描述符后,为什么两个文件描述符指向了同一个文件?

实际两个文件描述符中的ptr指针指向的是一个地址

 

(6)例子2:使用函数dup2函数可以制定文件描述符的位置,也就是说可以将文件描述符复制到任何一个位置

Dup2(源描述符,目标描述符)

 

例子代码:

 

 

 

 

三、下午的内容

 

1、管道:什么是管道文件?

创建管道文件命令mkfifo 1.pipe

注意,不可以使用vim打开管道,管道是用来通信的

 

设置一个读端口,设置一个写端口,也就是启动两个进程,就可以实现简单的管道通信

 

(1)实现简单的一句话通信

①设置读端read,int fdr=open(argv[1],O_RDONLY);

 

②设置写端口write

 

 

③使用makefile_more的makefile,之后使用命令:

 

(2)

①通信方式分3种:全双工、半双工、单工;管道属于半双工;

②管道通信相当于两个进程共享了一段缓冲区

③如何查看reader进程被卡住的状态?使用ps -elf|grep raed,即可查看进程的状态

(3)设置可以发送多个数据

①read.c和writer.c,设置可以发送多个数据

 

②当管道里没有数据的时候,reader是不会读的,read读取会阻塞

③后续操作截图:

 

 

 

 

(4)怎么写一个即时聊天工具呢?使用两条管道,就可以实现全双工

①再创建一个管道使用命令mkfifio 2.pipe

 

 

②要注意!可能会发生死锁问题!

要防止出现死锁问题!

双方要保持相同的手法

Chat1打开1号管道,以读的方式,chat2打开1号管道,以写的方式

Chat1打开2号管道,以写的方式,chat2打开2号管道,以读的方式
③chat1.c和chat2.c文件

 

④两个程序第一次打开的管道必须是同一个管道

⑤重新make一下

 

 

(5)打开了管道之后,如何写即时聊天?

①大致思路

 

 

②Chat1.c

 

 

③Chat2.c的内容

 

 

 

④执行截图:

 

 

 

⑤但是此时设置的聊天还是有一个bug,就是1个进程不能同时发送多条数据,有两个地方会出现卡住,一个是管道,一个是标准输入,如何解决?使用I/O多路转接模型(在第17页)

(6)修复单向关闭后,会出现大量空白的bug

 

①首先在func.h文件中,加入

#include<sys/select.h>

#include<sys/time.h>

 

func.h文件在Usr/include/func.h

 

 

 

 

 

②timeout是设置一个等待阈值;rdset是传入传出参数,

 

③Chat2.c的内容

 

 

 

 

 

 

 

 

 

(7)程序还有一个bug,就是在某一个进程结束管道后,另一个进程会突然冒出大量空白界面,如何解决?

 

原因?管道本来是有读端口和写端口,怎么判断另外一端口还在不在?

对于管道来讲,如果写端关闭,读端会直接返回0,而对于内核来讲,状态会被标识为可读;因为一直显示可读,就会一直转入该函数,但是可以读取到的都是0,所以就会疯狂狂打印

如何改造一下,使之不会疯狂打印?

 

read.c加一句

 

 

 

#include <func.h>

 

int main(int argc,char* argv[])

{

    ARGS_CHECK(argc,3);

    int fdr=open(argv[1],O_RDONLY);//1号管道

    int fdw=open(argv[2],O_WRONLY);//2号管道

    printf("I am chat1 fdr=%d,fdw=%d\n",fdr,fdw);

    char buf[128]={0};

    fd_set rdset;

    int ret;

    struct timeval timeout;

    while(1)

    {

        FD_ZERO(&rdset);

        FD_SET(STDIN_FILENO,&rdset);

        FD_SET(fdr,&rdset);

        bzero(&timeout,sizeof(timeout));

        timeout.tv_sec=3;

        ret=select(fdr+1,&rdset,NULL,NULL,&timeout);//rdset是传入传出参数

        if(ret>0)

        {

            if(FD_ISSET(STDIN_FILENO,&rdset))

            {

                memset(buf,0,sizeof(buf));

                ret=read(STDIN_FILENO,buf,sizeof(buf));

                if(0==ret)

                {

                    printf("broken up\n");

                    break;

                }

                write(fdw,buf,strlen(buf)-1);

            }

            if(FD_ISSET(fdr,&rdset))

            {

                memset(buf,0,sizeof(buf));

                ret=read(fdr,buf,sizeof(buf));

                if(0==ret)

                {

                    printf("byebye\n");

                    break;

                }

                printf("%s\n",buf);

            }

        }else{

            printf("timeout,come back,do other thing\n");

        }

    }

    close(fdr);

    close(fdw);

    return 0;

}

 

 

 

 

write.c同理

 

对于Ctrl+C强制断开的情况,加一句话

Chat1.c中

 

 

 

#include <func.h>

 

int main(int argc,char* argv[])

{

    ARGS_CHECK(argc,3);

    int fdw=open(argv[1],O_WRONLY);//1号管道

    int fdr=open(argv[2],O_RDONLY);//2号管道

    printf("I am chat2 fdr=%d fdw=%d\n",fdr,fdw);

    char buf[128]={0};

    fd_set rdset;

    int ret;

    while(1)

    {

        FD_ZERO(&rdset);

        FD_SET(STDIN_FILENO,&rdset);

        FD_SET(fdr,&rdset);

        ret=select(fdr+1,&rdset,NULL,NULL,NULL);//rdset是传入传出参数

        if(FD_ISSET(STDIN_FILENO,&rdset))

        {

             memset(buf,0,sizeof(buf));

             read(STDIN_FILENO,buf,sizeof(buf));

             write(fdw,buf,strlen(buf)-1);

        }

        if(FD_ISSET(fdr,&rdset))

        {

             memset(buf,0,sizeof(buf));

             ret=read(fdr,buf,sizeof(buf));

             if(0==ret)

             {

                 printf("byebye\n");

                 break;

             }

             printf("%s\n",buf);

        }

    }

    return 0;

}

 

 

 

 

2、I/O多路转接机制-select

(1)select最大可以监视1024个进程,因为fd_set中只可以监视1024;

(2)如何设置超时参数?再定义一个超时参数,每3秒就会打印一句话

额外:bzero命令可以清空内容,相当于C语言的memset,需要在func.h中增加#include<strings.h>;#include<string.h>

Chat1.c

看一下龙哥最新的chat1.c文件

 

 

 

(3)写事件,一个不读,另一个一直写,就会写满,怎么办?

创建一个新文件,叫做read.c,在另一个文件夹write_full中

 

写文件的内容

 

启动两个进程后,写进程会疯狂的往管道里写数据,睡眠函数除了sleep函数,还有usleep函数,微秒级的睡眠

读端口一断开,写端口会崩溃

读文件的内容:见具体的代码

 

 

(4)

一个文件既可以掌握读端口,也可以掌握写端口,具体例子见第18页

 

 

该例子在第18页

 

使用2条管道,既用于监视写事件,又可以监视读事件

 

创建了新文件在select_write文件夹下

 

文件write.c

 

清空文件可以使用FD_ZERO

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值