Linux开发_介绍目录编程、标准文件编程、Linux系统文件接口编程、GDB调试

118 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

介绍Linux下目录相关操作函数、文件目录状态获取方式、C标准与Linux下文件IO操作函数、安装SublimeText2编辑器,GDB调试工具基本使用。

任务1:目录操作

学习系统编程: 主要学习系统函数的调用。

 #include <stdio.h>
 /*
 int argc :表示传入的参数数量
 char **argv:存放传入的参数数据,本身是一个二维数组。
 argv[0] 表示第一个参数
 argv[1] 表示第二个参数
 */
 int main(int argc,char **argv)
 {
 int i;
 for(i=0;i<argc;i++)
 {
 printf("argv[%d]=%s\n",i,argv[i]);
 }
 return 0;
 }

文件操作函数: fopen、fclose、fread、fwrite…………

目录操作函数:

 include <sys/types.h>
 #include <dirent.h>
 DIR *opendir(const char *name); //打开目录
 struct dirent *readdir(DIR *dirp); //读取目录信息
 int closedir(DIR *dirp); //关闭目录
 struct dirent {
 ino_t d_ino; /* inode number */
 off_t d_off; /* offset to the next dirent */
 unsigned short d_reclen; /* length of this record */
 unsigned char d_type; /* type of file; not supported by all file system types */
 char d_name[256]; /* filename 文件名称 */
 };

(目录操作案例练习)

【1】实现ls *.c 类似的功能。 产品: 视频播放器、音乐播放器

【2】强化第一题。ls *.c

(1) 拼接路径: /mnt/hgfs/linux-share-dir/test/test.c (通过命令行传入路径)

示例:./a.out ./work/test .c

结果: ./work/test/123.c ./work/test/456.c

(2) 获取绝对路径: /mnt/hgfs/linux-share-dir/test/test.c

示例:./a.out ./work/test .c

结果: /user/work/test/123.c /user/work/test/456.c

【3】实现目录的拷贝。 类似cp命令

int mkdir(const char *pathname, mode_t mode);

(1) 实现一层目录的拷贝。

(2) 实现所有目录的拷贝。(扩展)

 char *strstr(const char *haystack, const char *needle);  
 const char *haystack:在哪里查找 
 const char *needle:查找的数据 返回值: 返回查找到的数据的首地址

【4】实现cat命令效果

(1) 示例: cat 123.c

(2) 示例: cat 123.c -n (扩展作业)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// ./a.out 123 456
//argc:传入参数的数量
//argv:存放传入参数的缓冲区
int main(int argc,char**argv) //char *argv[]
{
  if(argc!=2)
 	{
 		  printf("参数传入错误: ./a.out <file_name>\n");
 		  exit(-1);
 	}
 	
  FILE *file;
  
  //1. 打开文件
  file=fopen(argv[1],"rb"); //使用读权限打开文件
  if(file==NULL)
  {
     perror("文件打开失败!\n");	
     exit(-1); //结束进程--return
  }
  
  char buff[1024];
  int count;
  int i;
  while(1)
  {
  	 count=fread(buff,1,1024,file);	
  	 //printf("%s",buff);
  	 for(i=0;i<count;i++)
  	 {
  	 	   printf("%c",buff[i]);
  	 }
  	 if(count!=1024)
  	 	{
  	 	   	break;
  	 	}
  }

  //3. 关闭文件
  fclose(file);
  return 0;	
}

【5】实现du命令的功能。

(1) 示例: du 123.c 显示出文件的大小

(2) 示例: du 123.c -h 使用合理的单位显示出文件的大小(扩展)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc,char**argv) 
{
  if(argc!=2)
 	{
 		  printf("参数传入错误: ./a.out <src_file_name>\n");
 		  exit(-1);
 	}
 	
  FILE *file;
  long size;
  
  //1. 打开文件
  file=fopen(argv[1],"rb"); //使用读权限打开文件
  if(file==NULL)
  {
     perror("文件打开失败!\n");	
     exit(-1); 
  }
  fseek(file,0,SEEK_END);  //将文件指针偏移到文件尾
  size=ftell(file);
  printf("%s 文件大小: %d 字节。\n",argv[1],size);
  
  fseek(file,0,SEEK_SET);  //将文件指针偏移到文件头
  //3. 关闭文件
  fclose(file);
  return 0;	
}

1.1 获取当前目录绝对地址相关函数

 #include <unistd.h>
 char *getcwd(char *buf, size_t size);
 char *getwd(char *buf);
 char *get_current_dir_name(void); //获取绝对路径
 int chdir(const char *path); //修改当前目录,即切换目录,相当于 cd 命令

1.2 mkdir函数创建目录

 #include <sys/stat.h>
 #include <sys/types.h>
 ​
 int mkdir(const char *pathname, mode_t mode); // 777
 #include <sys/types.h>
 #include <sys/stat.h>
 ​
 mode_t umask(mode_t mask); //设置创建目录或者文件的默认权限
 一般在调用mkdir时,需要先调用umask(0);
 ​
 mode_t mode参数的填写说明:
 S_IRWXU 00700 user (file owner) has read, write and exe-cute permission
 S_IRUSR 00400 user has read permission
 S_IWUSR 00200 user has write permission
 S_IXUSR 00100 user has execute permission
 S_IRWXG 00070 group has read, write and execute permis-sion
 S_IRGRP 00040 group has read permission
 S_IWGRP 00020 group has write permission
 S_IXGRP 00010 group has execute permission
 S_IRWXO 00007 others have read, write and execute per-mission
 S_IROTH 00004 others have read permission
 S_IWOTH 00002 others have write permission
 S_IXOTH 00001 others have execute permission

1.3 获取目录和文件的状态信息

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 ​
 int stat(const char *path, struct stat *buf); //直接获取源文件的状态()
 ​
 int fstat(int fd, struct stat *buf); //获取已经打开成功的文件状态
 ​
 int lstat(const char *path, struct stat *buf); //不区分链接文件
 ​
 //存放文件的状态信息
 ​
 struct stat {
 ​
 dev_t st_dev; /* ID of device containing file */
 ​
 ino_t st_ino; /* inode number */
 ​
 mode_t st_mode; /* protection */
 ​
 nlink_t st_nlink; /* number of hard links */
 ​
 uid_t st_uid; /* user ID of owner */
 ​
 gid_t st_gid; /* group ID of owner */
 ​
 dev_t st_rdev; /* device ID (if special file) */
 ​
 off_t st_size; /* 保存文件的大小*/
 ​
 blksize_t st_blksize; /* blocksize for file system I/O */
 ​
 blkcnt_t st_blocks; /* number of 512B blocks allocated */
 ​
 time_t st_atime; /* time of last access */
 ​
 time_t st_mtime; /* time of last modification */
 ​
 time_t st_ctime; /* time of last status change */
 ​
 };
 ​
 m的参数:-->st_mode
 ​
 S_ISREG(m) 判断是否是普通文件
 ​
 S_ISDIR(m) directory? 目录
 ​
 S_ISCHR(m) character device?
 ​
 S_ISBLK(m) block device?
 ​
 S_ISFIFO(m) FIFO (named pipe)?
 ​
 S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
 ​
 S_ISSOCK(m) socket? (Not in POSIX.1-1996.)

任务2:带缓冲区的文件IO操作

文件中的3个标准指针:

 stderr Standard error output stream. 存放标准错误信息的文件
 ​
 stdin Standard input stream. 存放标准输入信息的文件
 ​
 stdout Standard output stream. 存放标准输出信息的文件

示例:

 #include <stdio.h>
 int main()
 {
 char buff[10];
 while(1)
 {
 if(fread(buff,1,10,stdin)>0)
 {
 printf("读出的数据=%s\n",buff);
 }
 }
 return 0;
 }

带缓冲区:这一系列函数适合操作普通文件。

size_t fread(void *restrict, size_t, size_t, FILE *restrict);
int fseek(FILE *, long, int);
size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict);
int fclose(FILE *);

任务3:非缓冲区的文件IO操作

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);

int open(const char *pathname, int flags, mode_t mode); //在创建文件的时候才调用。

ssize_t read(int fd, void *buf, size_t count);

ssize_t write(int fd, const void *buf, size_t count);

int close(int fd);

作业

【1】 练习read、write读写函数。

【2】将cat命令编写使用open一系列函数实现。

【3】将stat文件状态的时间转为标准时间打印出来。

st_atime=1516528093 st_mtime=1516586761 st_ctime=1516586761 以上3个值是秒单位的时间。 是从1970年1月1日0时0分0秒开始计算。

格式: xxxx年xx月xx日 xx时:xx分:xx秒 星期x

转换时间:(写出一个类似于时钟的程序,可以加一个闹钟,判断时间是否到达)

(1) 编写一个函数实现秒单位的时间转为标准时间

(2) 编写一个函数实现将标准时间转为秒单位

#include <time.h>
int main(int argc,char**argv)
{
while(1)
{
long cnt=time(NULL); //获取当前系统时间
sleep(1); //睡眠一秒钟
printf("cnt=%d\n",cnt);
}
return 0;
}

【4】扩展作业: 重写一个scanf与printf函数。

int printf(const char *format, ...); int scanf(const char *format, ...);

…可变形参

任务4:安装编辑器

下载SublimeText2安装包,安装SublimeText2编辑器。

【1】压缩与打包名称

解压命令的使用格式:tar -xvf <压缩文件的名称>

想要指定解压之后文件存放的位置: tar -xvf <压缩文件的名称> -C <指定的目录>

【2】 打包指定文件夹或者文件: tar -cvf <新文件的名称> <要打包的目录>

示例: [root@wbyq test]# tar cvf SublimeText2.tar SublimeText2

注意:压缩包不能直接在共享目录下解压。

运行软件:

(1) # ./sublime_text

(2)# ./sublime_text & (后台运行程序)

切换中文输入法:Ctrl+空格

linux操作系统保存可执行文件的环境变量: PATH

(1) 打印环境变量的值:echo $PATH

img

(2)修改环境变量:# vim /etc/profile (系统开机的时候自动执行)

img

(3) source命令立即生效环境变量。(只是针对当前的终端)

示例:# source /etc/profile

任务5: GDB调试器

使用GDB调试工具: gdb <可执行文件的名称>

示例: gdb a.out

要支持调试程序,需要在gcc编译的时候加上-g选项参数。

示例:gcc -g 123.c

常用的命令:

breakpoints -- 设置程序的断点(简写b)。 语法: b <行号>或者 b <函数名称>

running -- 开始运行程序(简写run)

list -- 打印出当前的代码

next -- 单步调试

quit -- 退出调试界面