posts - 200, comments - 8, trackbacks - 0, articles - 0

linux高级编程day03 笔记(转)

Posted on 2012-12-30 16:39 鑫龙 阅读(454) 评论(0)  编辑 收藏 引用 所属分类: 杨强linux视频笔记系列

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

  3.默认规则:
    a.不指定目标,执行第一个目标
    b.不指定make文件,默认文件是makefile Makefile
      makefile优先
  4.目标的调用规则:(make把目标当成当前文件夹下同名的文件)
    make执行目标:
      搜索与目标相同的文件
      如果文件存在,则判定文件是否被修改过。
      文件未被修改,则停止执行,输出提示
      文件修改过,则进行执行。(文件不存在属于被修改过范畴)

      比较:当前目标与依赖目标
  5.建议:
    只要有文件输出,就把任务作为一个目标,并且把输出的文件作为目标名。
    范例:
    input.o:input.c
       gcc -c -fpic input.c
    libdemo.so:input.o
       gcc -shared -olibdemo.so input.o
    demo:libdemo.so demo.c
       gcc demo.c -ldemo -L. -odemo
  
  6.潜规则(不建议)
    适用于:.c目标与.o目标。
    查找.o目标,目标不存在,就把.o替换成.c
    如果.c存在,实施潜规则:直接调用gcc把.c执为.o
  7.变量
    变量名=值 值
    
    $(变量名)  ${变量}  
  8.伪目标:
    不把目标作为文件处理的目标称为伪目标
    声明伪目标
    .PHONY=目标  

二、环境变量
  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表示.
         沾附的目的:防止有些权限的用户删除文件.
      
      程序在执行的时候到底拥有的是执行者用户的权限
      还是文件拥有者的权限.(看setUID)
       程序执行中有两个用户:
          实际用户:标示进程到底是谁
          有效用户:标示进程访问资源的权限
       上述一般情况是一样的,有时候被setUID改变      
   总结:
     沾附位的作用: 防止其他有写权限用户删除文件
     设置位的作用: 向其他执行者开发组或者用户的权限.
练习:
  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_RDONLY O_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(int fd);           

案例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,
);
    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:
  结构体读取
  描述:从键盘读取若干条数据,保存到文件
     数据追加
View Code 

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
struct stu
{
    int no;
    char name[20];
    float score;
};
/*
.判定文件是否存在,存在打开,不存在创建
.输入记录
.保存记录
.提示继续输入
.继续/不继续
.关闭文件
*/
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 存在的文件  新的文件名
    要求:
      文件存在就拷贝,不存在提示错误.

 


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理