天天看点

Ubuntu下UnixC第五天

回忆昨天课程内容

    一、内存管理

    进程的映像  代码段  数据段 堆 栈段

    变量的空间分配在什么地方,不同的段有不同的属性

    变量的生命周期  变量的作用域

    堆      手动释放free   p=NULL;

    进程  pid PCB  进程的映像是属于PCB的一个成员

    const 定义一个只读变量

    二、使用mmap将物理地址映射到进程的虚拟地址空间

    mmap munmap

    三、文件的操作

    open(2) close(2) read(2) write(2)

    文件描述符    进程的pid PCB 可变参数  

0标准输入 STDIN_FILENO

1标准输出 STDOUT_FILENO

2标准错误输出   STDERR_FILENO

umask 权限掩码

今天内容

一、lseek(2)

     #include <sys/types.h>

       #include <unistd.h>

       off_t lseek(int fd, off_t offset, int whence);

    功能:

    参数:

    fd      指定了要操作的文件

    offset

    whence-     SEEK_SET    offset

                         The offset is set to offset bytes.

                 SEEK_CUR   locat+offset

                        The offset is set to its current location plus offset bytes.

                  SEEK_END  文件的末尾+offset

                       The offset is set to the size of the file plus offset bytes.

    返回值:错误 (offset_t)-1 errno被设置

        成功 返回当前位置距离文件开头的字节数

二、使用mmap(2)讲文件映射到进程的虚拟地址空间,对内存进行操作,直接反应到文件

    代码参见 map.c

day05$od -tx1 -tc hello

0000000  68  65  6c  6c  6f  20  62  65  69  6a  69  6e  67  0a

          h   e   l   l   o       b   e   i   j   i   n   g  \n

0000016

day05$a.out hello

day05$od -tx1 -tc hello

0000000  34  33  32  31  6f  20  62  65  69  6a  69  6e  67  0a

          4   3   2   1   o       b   e   i   j   i   n   g  \n

0000016

高位字节存放在低地址     大端

高位字节存放在高地址    小端

编写程序,测试自己的主机字节序

三、文件描述符的复制

dup(2) dup2(2)

  #include <unistd.h>

       int dup(int oldfd);

    功能:复制一个文件描述符,使用最小的

    参数:

    oldfd 源描述符

    返回值:错误-1 errno被设置

        成功:返回新的文件描述符

       int dup2(int oldfd, int newfd);

    功能:复制一个文件描述符,使用newfd指定的,如果原来的描述符是打开的,将其关闭

    参数:

    oldfd 源描述符

    newfd 目的描述符

    返回值:错误 -1 errno被设置

        成功 返回newfd

    编写代码实现文件输出重定向  代码参见direct.c

四、获取文件的原数据

    什么是文件的元数据,文件是怎么存储的?

    一个文件包含两个部分内容  元数据和内容

    元数据是对一个文件的描述信息

    每个文件有且仅有一个inode,且每个inode都有自己的编号

    链接文件

    软链接

    硬链接  文件的inode是同一个

    ln 源文件 目标文件 之后两个文件inode相同

    stat(2)

     #include <sys/types.h>

       #include <sys/stat.h>

       #include <unistd.h>

       int stat(const char *pathname, struct stat *buf);

    功能:获取文件身份信息

    参数:

    pathname 指定文件的路径,获取这个文件的元数据

    buf 指定地址,将文件的元数据存储到buf指定的空间里

    返回值:

    struct stat?

    值-结果参数

       struct stat {

               dev_t     st_dev;        

               ino_t     st_ino;        

               mode_t    st_mode;       

               nlink_t   st_nlink;      

               uid_t     st_uid;        

               gid_t     st_gid;        

               dev_t     st_rdev;       

               off_t     st_size;        

               blksize_t st_blksize;    

               blkcnt_t  st_blocks;     

               struct timespec st_atim; 

               struct timespec st_mtim; 

               struct timespec st_ctim; 

           #define st_atime st_atim.tv_sec     

           #define st_mtime st_mtim.tv_sec

           #define st_ctime st_ctim.tv_sec

           };

    struct timespec{

        _time_t tv_sec;

        _syscall_slong_t tv_nsec;

    };

1970年1月1 0点0分0秒  unix诞生

将秒数转换为字符串

ctime(3)

 #include <time.h>

char *ctime(const time_t *timep);

功能:将秒数转换为分开的格式

参数:

timep 秒数

返回值:时间字符串,末尾为换行符

根据uid找到用户的名字

    系统中维护着用户的信息,所有用户的信息存放在/etc/passwd文件中

    tarena:x:1000:1000:ubuntu,,,:/home/tarena:/bin/bash

    nan:x:1000:1000:nan,,,:/home/nan:/bin/bash

    root:x:0:0:root:/root:/bin/bash

    getpwnam(3)

     #include <sys/types.h>

       #include <pwd.h>

       struct passwd *getpwnam(const char *name);

       struct passwd *getpwuid(uid_t uid);

      struct passwd {

               char   *pw_name;      

               char   *pw_passwd;    

               uid_t   pw_uid;       

               gid_t   pw_gid;       

               char   *pw_gecos;     

               char   *pw_dir;       

               char   *pw_shell;     

           };

     getgrnam(3)

    #include <sys/types.h>

       #include <grp.h>

       struct group *getgrnam(const char *name);

     struct group {

               char   *gr_name;       

               char   *gr_passwd;     

               gid_t   gr_gid;        

               char  **gr_mem;        

           };

根据gid找到用户组的名字

direct.c

#include<t_stdio.h>

#include<t_file.h>

#include<string.h>

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

    char *msg="stupid jerryFeng\n";

    //打开文件,以写的方式,文件不存在则创建

    //权限为0644,文件存在则清空

    int fd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0644);

    if(fd==-1) 

        E_MSG("open",-1);

//将标准输出描述符保存

    int s_fd=dup(1);

    //将标准输出重新定向到打开的文件

    dup2(fd,1);

    close(fd);

    write(1,msg,strlen(msg));

    //恢复标准输出

    dup2(s_fd,1);

    close(s_fd);

    write(1,msg,strlen(msg));

    return 0;

}

map.c

#include<t_file.h>

#include<t_stdio.h>

#include<sys/mman.h>

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

    //将文件映射到进程的内存

    int prot=PROT_READ|PROT_WRITE;

    int flags=MAP_SHARED;

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

    if(fd==-1)

      E_MSG("open",-1);

    void *p=mmap(NULL,32,prot,flags,fd,0);

    if(p==MAP_FAILED)

      E_MSG("mmap",-1);

    *((int *)p)=0x31323334;

    //解除映射

    munmap(p,32);

    close(fd);

    return 0;

}

s_big.c  //看自己的虚拟机是大端还是小端

#include<t_stdio.h>

typedef union{

    char c;

    short s;

}u_t;

int main(void){

    u_t temp;

    temp.s=0x0001;

    printf("temp.s:%p,%d\n",&temp.s,temp.s);

    printf("temp.c:%p,%p\n",&temp.c,temp.c);

    temp.c?printf("small\n"):printf("big\n");

    return 0;

}

stat.c

#include<t_stdio.h>

#include<t_file.h>

#include<time.h>

#include<pwd.h>

#include<grp.h>

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

    //获取文件的元数据,存储到buf

    struct stat buf;

    int s=stat(argv[1],&buf);

    if(s==-1) E_MSG("stat",-1);

    printf("hard links:%u\n",buf.st_nlink);

    printf("size:%ld\n",buf.st_size);

    printf("inode:%ld\n",buf.st_ino);

    printf("mtime:%s",ctime(&buf.st_mtime));

    printf("uid:%u\n",buf.st_uid);

    printf("username:%s\n",(getpwuid(buf.st_uid))->pw_name);

    printf("gid:%u\n",buf.st_gid);

    printf("group grname:%s\n",(getgrgid(buf.st_gid))->gr_name);

    return 0;

}

继续阅读