c++ 学习笔记(高级linux编程) day3

来源:互联网 发布:龙华行知小学 编辑:程序博客网 时间:2024/06/07 01:13

linux高级编程day03 笔记

一、make与makefile
  1.回顾:
    目标的语法
    目标名:依赖目标
      @命令
      @命令
      
    make的命令行使用
      make -f make脚本文件  目标名
  2.目标的划分
    目标依赖

  3.默认规则:
    a.不指定目标,执行第一个目标
    b.不指定make文件,默认文件是makefile Makefile
      makefile优先
  4.目标的调用规则:(make把目标当作文件)
    make执行目标:
      搜索与目标相同的文件
      如果文件存在,则判定日期。
      日期最新,则停止执行,输出提示
      日期不是最新,则进行执行。

      比较:当前目标与依赖目标
  5.建议:
    只要有文件输出,就把任务作为一个目标,并且把输出的文件作为目标名。
    
  6.潜规则(不建议)
    .c目标与.o目标。
    查找.o目标,目标不存在,就把.o替换成.c
    如果.c存在,实施潜规则:直接调用gcc把.c执为.o
  7.变量
    变量名=值值
    
    $(变量名)  ${变量}  
  8.伪目标:
    不把目标作为文件处理的目标称为伪目标
    声明伪目标  
没有:
  1.make的配置
  2.make的变量的操作函数
  3.多make文件使用

二、环境变量
  1.使用main的参数
  int main(int args,char *argv[],char **arge)
  {
  }
  命令行参数argv与环境行arge都是字符串数组.
  约定:最后一个字符串是NULL/0
  2.在C的标准库提供:外部变量
   extern char **environ;

#include <stdio.h>

#include <unistd.h>

extern char **environ;

int main(/*int args,char*argv[],char*arge[]*/)

{

   /*

   while(*arge)

    {

       printf("%s\n",*arge);

       arge++;

    }

   */

   /*

   int i=0;

   while(arge[i])

    {

       printf("%s\n",arge[i]);

       i++;

    }

   */

   while(*environ)

    {

       printf("%s\n",*environ);

       environ++;

    }

}

  3.修改获取某个环境变量
    getenv/setenv/unsetenv

#include <stdlib.h>

#include <stdio.h>

main()

{

   char *val;

    val=getenv("PATH");

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

}   

三、IO的基础
  1.认识内核对象
    不允许访问内核设备和内存,但可以通过内核系统函数去访问.
    对每个内核对象进行编号ID.
    如果访问内核对象,只能通过ID.
    编程模型:
      申请得到一个ID
      在内核系统函数中使用ID得到对应内核对象数据
  2.怎么访问文件
    使用函数,传递一个文件,系统打开文件,加载文件数据,
    返回一个ID.
    使用函数,传递ID,得到数据.
    使用函数传递ID,告诉系统释放文件.
        
    ID:文件描述符号.file description (fd)
    
    每个程序执行的时候都有一个目录,存放打开的文件描述符号
  3.每个程序默认打开三个文件设备:
    0:标准输入
    1:标准输出
    2:错误输出
  4.操作文件描述符号
    ssize_t write(int fd,
     void *buf,//要写入内核对象的数据
     size_t size);//写入数据大小
    返回:
      >0 实际写入的数据
      -1 写入错误 
    ssize_t read(int fd,
      void *buf,//返回数据的空间
      size_t size);//空间大小
    返回:
      >0:实际读取的数据
      =0:碰到文件结束符号EOF (ctrl+d)
      -1:读取错误
    
    建议:
      0:输入
      1:输出
      2:错误输出
课堂练习:
  1.使用write向0 1 2 写数据
  2.使用read从0 1 读取数据,并判定输入的情况,然后根据相应的结果输出提示

#include <stdlib.h>

#include <stdio.h>

main()

{

   //printf("%d\n",getpid());

   //while(1);

   /*

   int r=write(0,"Hello\n",6);

   write(1,"world\n",6);

   write(2,"louis\n",6);

   int a=20;

   

   write(1,&a,4);

   */

   char buf[32];

   //memset(buf,0,32);

   bzero(buf,32);

   

   int r=read(0,buf,30);

   printf("实际输入:%d\n",r);

   if(r>0)

    {

       buf[r]=0;

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

    }

   if(r==0)

    {

       printf("ctrl+d\n");

    }

   if(r==-1)

    {

       printf("输入错误!\n");

    }

}

三.基于文件的描述符号
  1.得到文件描述符号/释放文件描述符号
   a.文件类型
    目录文件d
    普通文件f
    字符设备文件c
    块设备文件b
    软连接文件l
    管道文件p
    socket文件s   
   b.文件的属性
     1.属性的表达方式:绝对模式(0666类似的八进制数),字符模式(rwx)
       0   0   0    0
          拥有者  组   其他用户
       0666
     2.文件的权限属性:
       读
       写
       执行
       粘附位权限
       用户设置位权限
       组设置位权限
      0   0        0     0       0
        特殊权限   Owner group  其他用户

       s:
       S
       t
       T
      2.1.  s设置位
          2:组设置位
          4:用户设置位
         s对执行有效
         无效的设置位使用S表示
         
         设置位向其他用户开放拥有者权限的权限.用户设置位
         设置位向其他用户开放组用户权限的权限.组用户设置位
         设置位只对执行程序有意义(执行权限有意义)
         
      2.2.  t设置位
          1:表示沾附位设置
          t对写文件有意义
         没有执行权限的沾附位使用T表示.
         沾附的目的:防止有些权限的用户删除文件.
      
      程序在执行的时候到底拥有的是执行者用户的权限
      还是文件拥有者的权限.
       程序执行中有两个用户:
          实际用户
          有效用户      
   总结:
     沾附位的作用: 防止其他有写权限用户删除文件
     设置位的作用: 向其他执行者开发组或者用户的权限.
练习:
  1.使用cat创建一个文件
  2.设置沾附位,并观察属性
  3.设置用户设置位, 并观察属性
  4.设置组设置位, 并观察属性
  5.考虑w权限与沾附位的关系
  6.考虑x权限与设置位的关系.

  2.通过文件描述符号读写各种数据.      
    open函数与creat函数

                int open(

                    const char *filename,//文件名

                    int flags,//open的方式[创建/打开]

                    mode_t mode//权限(只有创建的时候有效)

                    )

    返回:
      >=0:内核文件描述符号.
      =-1:打开/创建失败
  
    open的方式:
      必选方式:O_RDONLYO_WRONLY O_RDWR,必须选择一个
      创建/打开:O_CREAT
      可选方式:
          对打开可选方式:O_APPEND O_TRUNC(清空数据)
          对创建可选方式:O_EXCL
     组合:
        创建:
          O_RDWR|O_CREAT
          O_RDWR|O_CREAT |O_EXCL 
        
        打开:          
          O_RDWR
          O_RDWR|O_APPEND
          O_RDWR|O_TRUNC
     权限:
       建议使用8进制数
    关闭
    void  close(intfd);           

案例1:
  创建文件
案例2:
  创建文件并写入数据
    20  short float
    tom  20   99.99
    bush  70   65.00
    达内  40   100.00
  注意:
    文件的创建的权限受系统的权限屏蔽的影响
    umask    //显示屏蔽权限.
    umask 0666  //设置权限屏蔽.  
    
    ulimit -a 显示所有的其他限制.

/*创建文件*/

#include <fcntl.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

main()

{

   int fd;

   

   char name[20];

   short age;

   float score;

   char sex;

   

   fd=open("test.dat",

       O_RDWR|O_CREAT|O_EXCL,

       00666);

   if(fd==-1) printf("open error:%m\n"),exit(-1);

   

   

   //写第一条

   memcpy(name,"tom",strlen("tom")+1);

   age=20;

   score=99.99;

   sex='F';

   

   write(fd,name,sizeof(name));

   write(fd,&age,sizeof age);

   write(fd,&score,sizeof(float));

   write(fd,&sex,sizeof(sex));

   

   //写第二条

   memcpy(name,"Bush",strlen("Bush")+1);

   age=70;

   score=65.00;

   sex='M';

   write(fd,name,sizeof(name));

   write(fd,&age,sizeof age);

   write(fd,&score,sizeof(float));

   write(fd,&sex,sizeof(sex));

   

   //写第三条

   

   memcpy(name,"达内",strlen("达内")+1);

   age=10;

   score=99.00;

   sex='F';

   write(fd,name,sizeof(name));

   write(fd,&age,sizeof age);

   write(fd,&score,sizeof(float));

   write(fd,&sex,sizeof(sex));

        

   close(fd);

}

案例3:
  打开文件读取数据
  重点:
    怎么打开读取
    文件尾的判定
  
  基本类型的数据读写.

#include <fcntl.h>

#include <stdlib.h>

#include <unistd.h>

#include <stdio.h>

 

main()

{

   char name[20];

   short age;

   float score;

   char sex;

   int fd;

   int r;

   fd=open("test.dat",O_RDONLY);

   if(fd==-1) printf("open error:%m\n"),exit(-1);

   

   while(1)

    {

       r=read(fd,name,sizeof(name));

       if(r==0) break;

       r=read(fd,&age,sizeof(short));

       r=read(fd,&score,sizeof(float));

       r=read(fd,&sex,sizeof(sex));

       printf("%s,\t%4hd,\t%.2f,\t%1c\n",

                name,age,score,sex);

    }

   

   close(fd);

}

案例4:
  结构体读取
  描述:从键盘读取若干条数据,保存到文件
     数据追加

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#include <stdlib.h>

#include <string.h>

struct stu

{

   int no;

   char name[20];

   float score;

};

/*

1.判定文件是否存在,存在打开,不存在创建

2.输入记录

3.保存记录

4.提示继续输入

5.继续/不继续

6.关闭文件

*/

int openfile(const char *filename)

{

   int fd;

   fd=open(filename,O_RDWR|O_CREAT|O_EXCL,0666);

   if(fd==-1)//表示文件存在,则打开

    {

       fd=open(filename,O_RDWR|O_APPEND);

       return fd;

    }

   return fd;

}

void input(struct stu *record)

{

   bzero(record,sizeof(struct stu));

   printf("输入学号:");

   scanf("%d",&(record->no));

   printf("输入姓名:");

   scanf("%s",record->name);

   printf("输入成绩:");

   scanf("%f",&(record->score));

}

void save(int fd,struct stu *record)

{

   write(fd,record,sizeof(struct stu));

}

int iscontinue()

{

   char c;

   printf("是否继续输入:\n");

   //fflush(stdin);

   //fflush(stdout);

   scanf("\n%c",&c);   

   if(c=='Y' || c=='y')

    {

       return 1;

    }

   return 0;

}

 

int main()

{

   int fd;

   int r;

   struct stu s={0};

   fd=openfile("stu.dat");

   if(fd==-1) printf("openfile:%m\n"),exit(-1);

   

   while(1)

    {

       input(&s);

       save(fd,&s);

       r=iscontinue();

       if(r==0) break;

       system("clear");

    }

   close(fd);

   printf("输入完毕!\n");   

}

  3.文件描述符号与重定向
     1.判定文件描述符号与终端的邦定关系
     int isatty(int fd)
     返回非0:fd输出终端
        0:fd输出被重定向
     2.防止重定向
       /dev/tty

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#include <stdlib.h>

#include <string.h>

 

int main()

{

   int fd;

   printf("Hello\n");

   write(1,"World\n",6);

   fd=open("/dev/tty",O_WRONLY);

   if(isatty(1))

    {

       write(1,"notredir\n",9);

    }

   else

    {

       write(1,"redir\n",6);

    }

   write(fd,"Killer\n",7);

}   

总结:
  1.make的多目标依赖规则以及伪目标
  2.文件的创建与打开(了解设置位的作用)
  3.文件的读写(字符串/基本类型/结构体)
  4.了解描述符号与重定向

作业:
  1.完成上课的练习.
  2.写一个程序使用结构体读取1种的数据,
     并全部打印数据,
     并打印平均成绩
  3.写一个程序:
    查询1种的数据.比如:输入姓名,查询成绩
  4.写一个程序,录入保存如下数据:
    书名  出版社  价格  存储量  作者  
  5.写一个程序负责文件拷贝
    main 存在的文件  新的文件名
    要求:
      文件存在就拷贝,不存在提示错误.

0 0