b1.1Linux开发环境搭建
1)Linux虚拟机的配置

2)Xshell、Xftp、vscode与Linux虚拟机的连接

1.2GCC



1.3静态库的制作和使用

静态库制作的全过程

首先进入放置要制作成库的代码的原始文件。
使用gcc编译得到编译后的文件。

gcc -c add.c sub.c -I ../include/
-I指定编译的时候在上搜索include引用的文件
ar rcs libxxx.a xxx.o
前面是库的名字,后面是一系列制作库所使用的文件


参数大L是指定使用的库,参数小l是指定使用的库的名称。

1.4动态库的制作与使用




使用 ldd 可执行程序名称 查看可执行程序的动态库依赖


输入 evn 用于查看环境变量

下述方法是在一个 terminal 当中临时配置环境变量,只能在当前的 terminal 中使用,一旦更换 terminal,环境变量失效。

用 export 来配置环境变量
LD_LIBRARY-PATH = $LD_LIBRARY-PATH
这一步用来获取原来的环境变量
:冒号之后添加的是新增的环境变量


更换 terminal 之后,环境变量失效。

永久配置环境变量的方法:
1)用户级别的配置
进入到 /home/ 目录下,找到 bashrc

直接在最后一行用原来在 terminal 当中的配置方法来配置

配置完成后,使用 . 或者 source 使得新配置的文件生效

(2)系统配置
修改 /etc/ 当中的 profile 文件

依然使用同样的语句

配置完成后依然需要更新


(3)
由于 /etc/ld.so.cache 文件是二进制文件,无法直接修改,所以需要修改 /etc/id.so.conf


直接将文件的绝对路径添加到里面去


不建议将文件加入系统库文件所存放的目录,可能会误操作导致系统库文件被覆盖。

1.5 makefile在这里插入图片描述

如何写一个简单的 Makefile ?
首先新建一个 Makefile 文件

写文件

之后执行。

如果第一行规则当中需要的依赖不存在,先执行下面的规则,直到生成了所有的依赖后再执行第一条规则。



如果更改了 main.c





使用 clean 规则可以删除中间的生成的依赖

make + 规则 可以首先只执行指定的那一行

删除之后再执行 make 会重新执行一次,但是不执行 clean 因为这个规则与第一条规则无关。

如果认为创建一个 clean 文件会导致最后一个规则无法执行,因为这个规则没有依赖,会被认为是最新的。


加上关键字 PHONY 表示 clean 是一个伪目标,最后不会生成文件,此时即使 存在 clean 文件,最后一个规则依然能够执行


1.6 GDB 调试


在编译的时候,加入 -g 这个参数生成的文件可以调试。

使用 set args 和 show args 设置和显示参数

使用 q 或者 quit 来退出

输入 help 查看帮助手册

在 vim 里面使用 set nu 可以查看行号

如果没有生成可以调试的文件,而是直接生成可执行文件,则无法调试,因为可执行文件只有编译后的二进制代码,没有与源文件的对应信息。

生成的调试文件里面含有机器码与源文件对应的信息,如果删除源文件会导致无法调试。

关于源代码的显示
输入 list 默认显示 10 行源代码
输入回车默认执行上一次的指令


查看以第 20 行开始的中间的信息

显示某个函数的代码


多个文件编译成一个可执行文件进行调试,查看某个函数的源代码要制定文件名



输入回车会继续显示

如果没有输入行号会报错

如果多个文件编译成一个可执行文件进行调试,查看某个文件的源代码没有指定文件名,会默认查看 main函数 所在的文件。

查看当前能够输出的行号和设置一次能够查看的行号

使用断点调试
使用 break + 行号 来设置断点
使用 info 来查看断电的信息

b + 函数名 给函数打断点

b + 文件名 : 行号 给指定的文件和行号来打断点

删除断点

删除断点后再次添加断点,断点的编号在上一次添加的时候最大的断点的基础上增添。
disable + 断点编号,将断点设置为不可用
enable + 断点编号,将断点设置为可用

在设置断点的时候加上 if 条件语句,可以设置成为条件断点。

程序的运行过程
如果没有打断点,使用 start 进入程序的第一行,main函数 的第一行,c 遇到第一个断点就停止,没有断点就一直运行到底。

没有断点的话, run 就一直运行到底

打了断点之后,在断点的前一行停止执行。

输入 c 继续执行直到下一个断点。





循环到某一步,想跳出一个循环所具备的条件有:
1)循环中不能存在断点
2)当前的这一次循环要执行完。

使用 n 能够使程序向下执行一步,如果遇到函数就不会进入函数体。

使用 s 会一步一步往下执行进入函数体内。

使用 finish 可以跳出函数体,但是要满足几个条件
1)函数体内不能有断点

使用 print 可以查看某个变量具体的值,但是每次执行一次就得设置一次,如果想要每次停顿都能够显示变量的值,得使用 display 。

使用 info display 可以用来查看自动变量的信息

使用 undisplay 来删除自动变量

可以直接为变量赋值
通过 set var 变量名

1.8 标准 C库 的 I/O 函数

如何实现跨平台?
1)Java 虚拟机 ,为每一个平台设计一个专用的虚拟机,让其在虚拟机上面运行。
2)C库 使用操作系统提供的接口,在哪个平台上就使用哪个平台的 API。

文件描述符:
文件读写指针:有写指针和读指针,用于文件的读写,文件的读写是相对于存储位置而言。
C库 文件具有 I\O缓存区,将文件数据写入缓存区当中,当缓存区满了或者使用 flush函数 的时候将缓存区的内容写入磁盘当中。如果不经过缓存区,直接向磁盘写入文件,内存和磁盘数据交换的速度较慢,多次操作会大大降低数据的传输速度。


1.9 文件描述符

文件描述符是什么?
Linux 内核在 PCB 当中为每个进程维护了一个文件描述符表,用于记录该进程打开的文件。
每个进程的文件描述符表都是从0开始,可能指向相同的文件,也可能指向不同的文件。

每次打开一个文件都创建了相应的文件描述符,和指向文件的指针。

其中标准输入、标准输出、标准错误指向当前打开的终端。
POSIX标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号。
当前进程在新打开一个文件,该文件的文件描述符从 3 开始。

进程通过文件描述符,查找自身的文件描述符表,得到文件指针,用文件指针在系统级的打开文件表中找到 inode 指针,通过 inode 指针找到对应的真实的文件。

我不明白的地方是,这三个数字算是三个文件描述符吗?
是的。
在哪里?有多大?如何创建?如何修改?如何删除?
如何得到文件描述符?

参考文章:理解文件描述符https://www.jianshu.com/p/a2df1d402b4d

1.10 open 函数
1)open 函数打开文件
C语言里面没有函数重载,这两个同名不同参的函数的实现不是通过重载,而是通过可变参数模板。

使用下面的命令查找 I/O库函数有关的指令

#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int open(const char *pathname, int flags);//flags 是定义的文件权限的标记,文件的读写权限之类的。int open(const char *pathname, int flags, mode_t mode);



测试文件:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include<unistd.h>
int main(void){//打开一个文件int fd = open("a.txt",O_RDONLY);if(fd == -1){perror("open");}//关闭相应的文件close(fd);return 0;
}

测试结果:

2)使用 open 函数创建文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include<unistd.h>
int main(void){int fd = open("create.txt",O_RDWR | O_CREAT,0777);if(fd == -1){perror("open");}close(fd);//printf("%hx",umask);return 0;
}

1.11 read 和 write 函数
read 函数

write 函数

#include<unistd.h>
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include <fcntl.h>
int main(void){//1、通过 open 打开要复制的文件int srcfd = open("a.txt",O_RDONLY);if(srcfd == -1){perror("open");return -1;}//2、创建一个新的文件用作拷贝的目的文件int destfd = open("b.txt",O_WRONLY | O_CREAT,0664);if(destfd == -1){perror("open");return -1;}//3、频繁的读写操作char buf[1024] = {0};int len = 0;while ((len = read(srcfd,buf,sizeof(buf))) > 0){write(destfd,buf,len);}//关闭文件close(srcfd);close(destfd);return 0;
}

1.11 sleek 文件



使用 lseek 来拓展文件,第一次运行后的结果

要想成功拓展,需要在后面写入一个字符

#include<unistd.h>
#include<sys/types.h>
#include<stdio.h>
#include<sys/stat.h>
#include <fcntl.h>
int main(void){//open the fileint fd = open("hello.txt",O_RDWR);if(fd == -1){perror("open");return -1;}//extend the fileint ret = lseek(fd,100,SEEK_END);if(ret == -1){perror("lseek");return -1;}//write a characterwrite(fd," ",1);close(fd);return 0;}


拓展文件的作用是:当下载一个大小为 5GB 文件的时候,提前占用好磁盘空间,防止其他文件向磁盘内写入造成磁盘空间割裂。

1.12 stat 文件

通过 stat 获取文件的大小

#include<unistd.h>
#include<sys/types.h>
#include<stdio.h>
#include<sys/stat.h>
#include <fcntl.h>
int main(void){struct stat statbuff;//int ret = stat("a.txt",statbuff);int ret = stat("a.txt",&statbuff);if(ret == -1){perror("stat");return -1;}printf("size:%ld\n",statbuff.st_size);return 0;}

lstat 函数的用法:
链接 a.txt 与 b.txt

使用 stat 获取的是 b.txt文件的信息,但是打开 b.txt 获得的是 a.txt 文件的信息,
如果想获得的是 a.txt 文件的信息,要使用 lstat

1.13 实现 ls-l 功能的函数

#include<unistd.h>
#include<sys/types.h>
#include<stdio.h>
#include<sys/stat.h>
#include <fcntl.h>
#include<pwd.h>
#include<grp.h>
#include<time.h>
#include<string.h>
int main(int argc,char *argv[]){if(argc < 2){printf("%s filename.\n",argv[0]);return -1;}struct stat st;int ret = stat(argv[1],&st);if(ret == -1){perror("stat");return -1;}//获取文件类型和文件权限char perms[11] = {0};switch (st.st_mode & S_IFMT){//符号链接case S_IFLNK:perms[0] = "l";break;//目录case S_IFDIR:perms[0] = "d";break;//普通文件case S_IFREG:perms[0] = "-";break;//快文件case S_IFBLK:perms[0] = "b";break;case S_IFCHR:perms[0] = "c";break;case S_IFSOCK:perms[0] = "s";break;case S_IFIFO:perms[0] = "p";break;default:perms[0] = "?";break;}//判断文件的访问权限//文件所有者perms[1] = (st.st_mode & S_IRUSR ? "r" : "-");perms[2] = (st.st_mode & S_IWUSR ? "w" : "-");perms[3] = (st.st_mode & S_IXUSR ? "x" : "-");
//文件所在组perms[4] = (st.st_mode & S_IRGRP ? "r" : "-");perms[5] = (st.st_mode & S_IWGRP ? "w" : "-");perms[6] = (st.st_mode & S_IXGRP ? "x" : "-");
//其他人perms[7] = (st.st_mode & S_IROTH ? "r" : "-");perms[8] = (st.st_mode & S_IWOTH ? "w" : "-");perms[9] = (st.st_mode & S_IXOTH ? "x" : "-");//硬连接数int linkNum = st.st_nlink;//文件所有者char *fileuser = getpwuid(st.st_uid)->pw_name;//文件所在组char *fileGrp = getgrgid(st.st_gid)->gr_name;//文件大小int fileSize = st.st_size;//获取修改的时间char *time = ctime(&st.st_mtime);char mtime[512];strncopy(mtime,time,strlen(time)-1);char buf[1024];sprintf(buf, "%s %d %s %s %d %s %s",perms,linkNum,fileuser,fileGrp,fileSize,mtime,argv[1]);printf("%s\n",buf);return 0;
}

1.14文件操作函数介绍
access 函数

 #include <unistd.h>
int access(const char *pathname, int mode);
作用:判断某个文件是否有某个权限,判断某个文件是否存在。
参数:
-pathname :判断文件的路径
-mode:
R_OK 判断文件是否有读权限
W_OK 判断文件是否有写权限
X_OK 判断文件是否有执行权限
F_OK 判断文件是否存在
返回值:成功返回0,失败返回-1

测试代码

#include<unistd.h>
#include<stdio.h>
int main(void){int ret = access("a.txt",F_OK);if(ret == -1){perror("access");}printf("文件存在!!!\n");return 0;
}

chmod 函数

 #include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
作用:修改文件的权限
参数:
-pathname 需要修改的文件的参数
-mode 需要修改的权限值,八进制的数
返回值:成功返回0,失败返回-1

测试用例:

#include <sys/stat.h>#include<stdio.h>
//int chmod(const char *pathname, mode_t mode);
int main(void){//修改前文件的权限,//-rw-r--r-- 1 three three  19 12月  2 15:57 a.txtint ret = chmod("a.txt",0775);if(ret == -1){perror("chmod");return -1;}printf("修改成功!!!");//修改后-rwxrwxr-x 1 three three  19 12月  2 15:57 a.txt*return 0;
}

chown 函数

 #include <unistd.h>int chown(const char *pathname, uid_t owner, gid_t group);

用命令行查看和创建用户

 #include <unistd.h>#include <sys/types.h>int truncate(const char *path, off_t length);作用:扩展或缩减文件的尺寸。参数:- path需要修改的文件的路径。- length修改后的文件的大小
返回值:成功返回0,

2021-11-25牛客网项目第一章——Linux系统编程入门相关推荐

  1. 2022-1-14牛客C++项目 —— 第二章 Linux多线程编程(gdb多进程调试)

    复习所用的问题 1.如果有多个进程,如何进行进程调试的切换? 2.当调试一个进程的时候,其他的进程会运行吗?如果会如何让他们不运行? 3.如果中途将挂起的程序修改成不挂起会有什么样的后果?如何解决? ...

  2. 仿牛客网项目第二章:开发社区登录模块(详细步骤和思路)

    目录 1. 发送邮件 1.0 三步走 1.1 邮箱设置 1.2 Spring Email 1.3 模板引擎 1.4 发送邮件的过程 1.5 检验发送邮件的过程 2. 开发注册功能 2.0 注册功能的步 ...

  3. 2022-1-15 牛客C++项目——第二章 Linux 多进程开发

    一.进程的的退出 问题:为什么使用标准 C 库函数和使用 Linux 的系统函数最后会有两个截然不同的结果呢? exit() #include<stdio.h> #include<s ...

  4. 云服务器上部署仿牛客网项目

    云服务器上部署仿牛客网项目 安装JRE 安装Maven 安装MySQL 给mysql导入数据 安装Redis 安装kafka 安装ElasticSearch Wkhtmltopdf 安装tomcat ...

  5. 牛客网——2017校招真题在线编程(pythonC++)

    牛客网--2017校招真题在线编程(python&C++) 1.n个数里的最小k个 题目描述 找出n个数里最小的k个 输入描述: 每个测试输入包含空格分割的n+1个整数,最后一个整数为k值,n ...

  6. c语言程序第一章编程,c语言程序的设计第一章 C语言编程入门.ppt

    c语言程序的设计第一章 C语言编程入门 第1章 C语言编程入门 本章是本书的入门篇,专为初学者熟悉编程过程.掌握程序结构而准备的. 本章学习目标 ? 1)? 能够通过模仿与改变来构造带有测试函数的C语 ...

  7. 牛客网项目1:开发社区首页

    总结在先: ①首先根据每张表创建相对应的实体类,该实体类中的属性与表中的字段名相同: ②由于每张表都需要一些增删改查的方法,因此需要创建Mapper接口(每张表各一个),接口中放有对应表的增删改查方法 ...

  8. 仿牛客网项目第五,六章:异步消息系统和分布式搜索引擎(详细步骤和思路)

    目录 1. Kafka:构建TB级异步消息系统 1.0 同步/异步消息的区别 1.1 项目的目的 1. 2 阻塞队列实现异步消息系统 1.4 Kafka入门 1.5 Spring整合Kafka 1.6 ...

  9. 牛客网项目3:注册、激活功能

    思路汇总 ①注册功能: 首先在主页index,点击注册:<a class="nav-link" th:href="@{/register}">注册& ...

最新文章

  1. 3D惯导Lidar SLAM
  2. Composer使用
  3. 对声音信标信号的采样频率
  4. golang 文件(文件打开,文件写入,文件读取,文件删除)的基本操作
  5. stat()函数:获取文件状态
  6. uboot启动第一阶段——start.S
  7. 逆波兰表达式(信息学奥赛一本通-T1198)
  8. Jenkins报错Error fetching remote repo 'origin'真正解决办法
  9. windows传文件到linux服务器--- secureCRT PK xftp
  10. python r语言 数据分析_PythonR语言-将Python和R整合进一个数据分析流程
  11. P2023 [AHOI2009]维护序列
  12. 完了!Oracle 被虐!MySQL 登顶 Top1!原来这么多人都在用
  13. 小学计算机英语,小学英语流利读电脑版
  14. 单链表学生管理系统(0723-林雪阵)
  15. java学习day10(Java基础)特殊类
  16. Right-BICEP 测试四则运算程序
  17. mysql 切分_Mysql字符串切分
  18. 168.Vue.js智能扫码点餐系统(二)【搭建Vue开发环境】2019.03.18
  19. 微软WP与Win8应用商店软件总数已突破40万
  20. 是否能构成三角形java

热门文章

  1. Nagios和商业开源网管软件SugarNMS的功能介绍和区别
  2. SONA Topology
  3. 【剑指Offer(专项突破)】002. 二进制加法(Java实现) 详细解析
  4. c语言自动转汇编,怎么将c语言转变为汇编语言
  5. linux的scp命令用不了,CentOS使用不了scp命令怎么办
  6. 《原神》甘雨搭配攻略分享:如何选甘雨搭配圣遗物?
  7. PN532资料 NFC RFID V3模块
  8. Gateway--服务网关
  9. 身份证实名认证查询校验接口_身份证二要素API接口
  10. 思维导图XMind中如何换行