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;
}