2021-11-25牛客网项目第一章——Linux系统编程入门
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系统编程入门相关推荐
- 2022-1-14牛客C++项目 —— 第二章 Linux多线程编程(gdb多进程调试)
复习所用的问题 1.如果有多个进程,如何进行进程调试的切换? 2.当调试一个进程的时候,其他的进程会运行吗?如果会如何让他们不运行? 3.如果中途将挂起的程序修改成不挂起会有什么样的后果?如何解决? ...
- 仿牛客网项目第二章:开发社区登录模块(详细步骤和思路)
目录 1. 发送邮件 1.0 三步走 1.1 邮箱设置 1.2 Spring Email 1.3 模板引擎 1.4 发送邮件的过程 1.5 检验发送邮件的过程 2. 开发注册功能 2.0 注册功能的步 ...
- 2022-1-15 牛客C++项目——第二章 Linux 多进程开发
一.进程的的退出 问题:为什么使用标准 C 库函数和使用 Linux 的系统函数最后会有两个截然不同的结果呢? exit() #include<stdio.h> #include<s ...
- 云服务器上部署仿牛客网项目
云服务器上部署仿牛客网项目 安装JRE 安装Maven 安装MySQL 给mysql导入数据 安装Redis 安装kafka 安装ElasticSearch Wkhtmltopdf 安装tomcat ...
- 牛客网——2017校招真题在线编程(pythonC++)
牛客网--2017校招真题在线编程(python&C++) 1.n个数里的最小k个 题目描述 找出n个数里最小的k个 输入描述: 每个测试输入包含空格分割的n+1个整数,最后一个整数为k值,n ...
- c语言程序第一章编程,c语言程序的设计第一章 C语言编程入门.ppt
c语言程序的设计第一章 C语言编程入门 第1章 C语言编程入门 本章是本书的入门篇,专为初学者熟悉编程过程.掌握程序结构而准备的. 本章学习目标 ? 1)? 能够通过模仿与改变来构造带有测试函数的C语 ...
- 牛客网项目1:开发社区首页
总结在先: ①首先根据每张表创建相对应的实体类,该实体类中的属性与表中的字段名相同: ②由于每张表都需要一些增删改查的方法,因此需要创建Mapper接口(每张表各一个),接口中放有对应表的增删改查方法 ...
- 仿牛客网项目第五,六章:异步消息系统和分布式搜索引擎(详细步骤和思路)
目录 1. Kafka:构建TB级异步消息系统 1.0 同步/异步消息的区别 1.1 项目的目的 1. 2 阻塞队列实现异步消息系统 1.4 Kafka入门 1.5 Spring整合Kafka 1.6 ...
- 牛客网项目3:注册、激活功能
思路汇总 ①注册功能: 首先在主页index,点击注册:<a class="nav-link" th:href="@{/register}">注册& ...
最新文章
- 3D惯导Lidar SLAM
- Composer使用
- 对声音信标信号的采样频率
- golang 文件(文件打开,文件写入,文件读取,文件删除)的基本操作
- stat()函数:获取文件状态
- uboot启动第一阶段——start.S
- 逆波兰表达式(信息学奥赛一本通-T1198)
- Jenkins报错Error fetching remote repo 'origin'真正解决办法
- windows传文件到linux服务器--- secureCRT PK xftp
- python r语言 数据分析_PythonR语言-将Python和R整合进一个数据分析流程
- P2023 [AHOI2009]维护序列
- 完了!Oracle 被虐!MySQL 登顶 Top1!原来这么多人都在用
- 小学计算机英语,小学英语流利读电脑版
- 单链表学生管理系统(0723-林雪阵)
- java学习day10(Java基础)特殊类
- Right-BICEP 测试四则运算程序
- mysql 切分_Mysql字符串切分
- 168.Vue.js智能扫码点餐系统(二)【搭建Vue开发环境】2019.03.18
- 微软WP与Win8应用商店软件总数已突破40万
- 是否能构成三角形java