linux系统编程之二

1)mmap内存映射的案例(映射为int类型)

#include<sys/types.h>
#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>
#include<error.h>
#include<errno.h>
#include<unistd.h>
#include<sys/mman.h>

int main(int argc, char** argv)
{
    int fd = open("test.txt",O_RDWR);
    if(fd < 0)
    {
        perror("open file");
        exit(1);
    }
    void* p = mmap(NULL,6,PROT_WRITE,MAP_SHARED,fd ,0); //创建一个内存映射关系
    int* iptr = (int*)p;
    iptr[0] = 0x30313233;
    munmap(p,6); //取消一个内存映射关系
    return 0;
}

2)内存映射的案例(映射为char类型)
int main(int argc, char** argv)
{
    int fd = open("test.txt",O_RDWR);
    if(fd < 0)
    {
        perror("open file");
        exit(1);
    }
    void* p = mmap(NULL,6,PROT_WRITE,MAP_SHARED,fd ,0); //创建一个内存映射关系
    char* iptr = (char*)p;
    iptr++;
    iptr[0] = 0x34;
    iptr[1] = 0x35;  
    munmap(p,6); //取消一个内存映射关系
    return 0;
}

2)od命令的使用,及vim的两种查找方式

1)按字符形式和16进制形式显示一个文本;od命令使用
 od -tx1 -tc test.txt //如果是按十进制的,这样:od -td1 -tc test.txt

//vim查找的两种格式:
2)如果是自己的文件,用vim打开的话,查找文件是":/xxx",如果是如man 2 mmap等打开系统参考文件的话,不要有":",直接“/xxx”即可;
3)TCGETS的:TC意思是终端控制
4)ls -R 递归打印文件;如果是目录,目录里面还有文件的话;

3)inode-Table和data block,用的是stat系统函数;

常规文件:文件的数据存储在数据块中;
目录:该目录下的所有文件名和目录名存储在数据块中。(注意:文件的其他信息保存在该文件的inode中);
所以,从上面看,如果要查看一个文件,需要不断的在inode和数据块中来回反复横跳;
说明:".",这个点就是记录的当前的inode信息,".."记录的是上一层的inode信息;
文件夹的大小一般都是4096字节的整数倍;
如果需要stat函数编程,最好参考linux手册;

5)课后学习这些函数(都和inode相关的)
access chmod fchmod chown fchown utime truncate link unlink rename readlink mkdir rmdir
通过不断学习,系统函数的有两种传参,第一个是路径,另外一个是文件描述符fd;如stat,fstat等待;有'l'的,就和软链接有关,如lstat函数;
软链接是真正创建了一个inode文件!!! 硬连接是给一个文件起了一个别名。
跟踪程序的系统调用:使用方法: strace命令: strace ./target 或者是strace ls,查看ls命令的系统调用;

4)利用openDir,readDir closeDir及stat等函数,设计一个简单的ls -R命令;

/*功能:
 *实现一个简易的ls -R功能,将目录里的内容,遍历打印出来。
 *文件的名字及目录深度不能太长,否则会报错;
*/
#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
#include<error.h>
#include<errno.h>
#include<unistd.h>
#include<sys/stat.h>
#include<dirent.h>
#include<sys/ioctl.h>
#include<string.h>

void printDir(char*  path)
{
    char pathname[1024];
    DIR* dir;
    struct dirent* dp;
    struct stat st;

    dir = opendir(path); 
    while(dp = readdir(dir)) //只要是文件夹不为空,就读;自己写的可以
    {
        if( !strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") )    continue;         
        sprintf(pathname,"%s/%s",path,dp->d_name); //字符串拼接
        stat(pathname,&st);
        if(S_ISDIR(st.st_mode)) //是否是路径
        {
            printDir(pathname); //如果是路径,则递归调用printDir
        }
        else if(S_ISREG(st.st_mode))
        {
            printf("%st",dp->d_name);
        }
    }
    putchar(10);
    closedir(dir);
}

int main(int argc, char** argv)
{
    if(argc < 2)
    {
        perror("open file");
        exit(1);
    }    
    printDir(argv[1]);
    return 0;
}
 

5)dup和dup2彻底的学会了,案例代码如下:

#include<sys/types.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<unistd.h>
#include<fcntl.h>
//dup:    和返回值有关系:    是复制一个fd,让dup返回的fd和参数fd指向同一个文件;dup函数一个参数
//dup2:   和返回值没关系;    是将新的fd和旧的fd指向同一个文件,dup2是两个参数;
int main(int argc, char** argv)
{
    int fd ,save_fd;
    fd = open("test.txt",O_RDWR); //fd应该是3;
    if(fd < 0)
    {
        perror("open file");
        exit(1);
    }
    save_fd = dup(1);  //save_fd 应该是4,从最小开始
    dup2(fd,1); //让1指向fd,fd = 3;
    close(fd); //不是真正关闭
    //经过上面3条语句,4指向了out,1指向了test.txt;
    write(1,"hello",6); //标准输出上,把数据写到test.txt文件里面;
    dup2(save_fd,1); //还原
    write(1,"hello",6); //标准输出上,可以打印到屏幕上;
    close(save_fd);
    return 0;
}