Linux gcc day8 gdb进程概念

本文详细介绍了Linux和Windows下调试的区别,特别是在C99模式下使用gdb进行命令行调试的方法。讨论了编译错误处理、gdb基本操作(如设置断点、运行和查看变量)以及进程管理和系统调用的概念,包括fork在Linux创建子进程中的应用。
摘要由CSDN通过智能技术生成

 已经学习了

调试

Linux下的调试和windows下有区别吗?

1、调试思路上,一定时一样的

2、调试的操作方式、一定时不一样的-------》命令行调试gdb

注意编译报错问题

error: 'for' loop initial declarations are only allowed in C99 mode

note: use option -std=c99 or -std=gnu99 to compile your code

error: 'for' loop initial declarations are only allowed in C99 mode_‘for’ loop initial declarations are only allowed i-CSDN博客

 实验

创建一个.c文件

  1 #include <stdio.h>
  2 #include <time.h>   //可用man 3 time  查看用法

  3 void Print(int sum)
  4 {
  5     long long timestamp = time(NULL);//时间戳 
  6     printf("sum = %d  , timestamp=%lld\n",sum,timestamp);                               
  7 }
  8 int AddToVal(int from,int to)
  9 {
 10     int sum =0;
 11     int i;
 12     for( i= from; i < to; i++)
 13     {
 14         sum += i;
 15     }
 16     return sum;
 17 }
 18 
 19 int main()
 20 {
 21 
 22     int sum = AddToVal(0,100);
 23     Print(sum);
 24 
 25     return 0;
 26 }
~

可以用在线工具转换一下时间戳 

如果出现bash 提醒证明没有安装,就需要

yum install -y gdb

gdb [文件名]

 

注意现在时不可以调试的 

要知道我们的版本是要在debug下才可以调试,在release版本下是进行不了调试的

为什么要有debug版本和release版本

因为debug版本是个程序员调试的

release是给用户使用的

所以debug版本的体积肯定比release板的大

 如何让它gcc编译出来就是debug版本呢?

gcc [文件.c] -o [修改名字]  -g    //-g就是指定为debug版本

修改makefile

readelf -S [可执行程序文件]    //可以读取可执行程序二进制格式

//读到了很多不懂的东西,反正要知道可执行文件并不是简单的二进制,而是分了很多各区就可以

readelf  -S 【可执行文件】

这样太多信息了

readelf -S 【可执行文件】| grep debug

gdb 操作

显示代码

(gdb) l 0  //从第0行显示     -list

(gdb) l 1 //从第1行显示

l 0  //执行命令后

按回车会自动显示下行代码因为会记住命令

打断点 breakpoint

(gdb) b n    //给第n行打断点 ---形成编号,break也可以打断点

这里打了断点不像windows下可以看到断点,如何查看断点呢?

(gdb) info b  //查看断点信息---看到编号

(gdb)  d   [编号]  //去掉断点  delete

(gdb) r   //运行起来并来到断点处

调试运行 r --run

逐过程  :n----next   //到下一行

逐语句:s ----step

(gbd) c         //运行至下一个断点处

bt  //调用堆栈

finish    //跑完逐语句的当函数

p    //临时查看变量的值

display  //长显示变量的值

undisplay

until N

为什么会来到18行?

总结下:

-------=======================================================------------------------

disable breakappoint [编号]      //关闭断点,并不是取消断点

enable [编号]       //打开断点

冯诺依曼体系结构 

这里的存储器指的是谁?

内存:掉电易失

磁盘(外存):永久性存储能力

外设((输入设备和输出设备)或者仅输入仅输出):网卡和磁盘(都是输入输出 )

CPU:运算器+控制器+其他       (计算的)
存储器(内存)                           (临时存储)较快
外设                                              (永久存储)较慢

CPU 其实只可以被动接受别人的指令,别人的数据- - -》执行别人的指令计算别人数据的目的  

CPU有自己的指令集才可以认识到别人的指令

我们写代码,编译本质是做什么?将二进制可执行程序编译成指令,才可以让CPU认识

 

将外设上的数据预先存进内存里,定期再刷新,就可以很好的解决cpu和外设读取写入数据的差异 

操作系统帮我们做策略(帮我们管理软硬件,临时数据的处理,刷新数据,清理,增加)

所以开机要加载操作系统

硬件和软件的完美结合就是计算机

将外设数据搬到内存中,内存中的数据写入到外设中的过程叫IO的过程INPUT/OUTPUT

总结:

在数据层面

cpu不和外设直接沟通,只和内存打交道

为了提高整机效率

example:

进度条 明明调用了printf为什么没被打印出来?显示屏是外设,代码加载到cpu不是直接输出到外设而是加载到内存中定期刷新的,这也是体系结构可以解释的

cpu的控制器:状态捕捉

cpu运算器:算术运算和逻辑运算

操作系统 

是一个进行软硬件的管理

对于管理者的理解:

管理者不需要和被管理者直接交互依旧能够把被管理对象管理起来

管理者:需要具备重大事宜决策能力

如何做到的?

管理本质是管理者对数据的管理

我和管理者不需要有交互,但是我的所有数据,早就在管理者手上而且一直在更新

硬件做管理本质先描述再组织,描述后有了对应的内核的数据结构,再用特定数据结构将对象管理起来

总结:

1、做管理本质上是对数据进行管理

2、拿数据是有特定的驱动程序进行的

3、操作系统拿到数据之后要对数据进行描述(磁盘是磁盘的,键盘是键盘的),对应的设备再组织用特定的数据结构组织进行管理(先描述再组织)、

------------============================================----------------------------

银行与计算机软硬件体系结构的比较

系统调用层(保护操作系统)

shell(指令操作)c库(编程操作)。。。。等:

当我们向显示器打印是不是硬件写入?

显示器属于输出外设,在程序运行时,调用库中的printf,根据冯诺依曼体系结构,从外设数据打入内存中,再由CPU处理返回给内存再打印到外设上,所以当我们调用printf,c++中的cout并不是直接打入硬件上的,其实是printf调用了操作系统接口,让操作系统帮我们访问硬件打印的

其实硬件写入是一件成本很高的事情,我们第一次学习hello world就是输出到显示屏,不是库写的多好,而是操作系统给我们提供了接口

软硬件结构图:

系统调用和库函数概念

1、在开发角度,操作系统对外会表现为一个整体    但是会暴露自己的部分接口,供上层开发使用,这部分    由操作系统提供的接口,叫做系统调用。
2、系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。 

什么是进程?

struct task_struct    内核结构体 -》 内核对象task_struct 对象--》将该结构和你的代码和数据关联起来--》先描述,在组织的工作

注意:

进程=内核数据结构(task_struct)+进程对应的磁盘代码

为什么会有PCB(task_struct)结构体呢?

管理的本质是对数据做管理, 所以就要先拿到数据,拿到的数据可能很多、乱、杂。所以要对数据进行归类,根据先描述再组织,和面向对象的思想,提取对应的数据进行(按照统一标准)管理

操作系统是一个软件,它早就加载到内存中一直运行着,当要启动一个程序所谓的把磁盘上的程序加载到内存

----===---=====----============-----------------=================-----=================

见见进程:

windows下:

实验Linux

如何查看进程呢? 

ps ajx              //查看所有进程可以加一些指令一起和管道使用

ps ajx | grep [你要查的进程]    //grep  行过滤

小技巧:

Linux中,进程都拥有以下的ID

  • Process ID(PID)
    Linux中标识进程的一个数字,它的值是不确定的,是由系统分配的(但是有一个例外,启动阶段,kernel运行的第一个进程是init,它的PID是1,是所有进程的最原始的父进程),每个进程都有唯一PID,当进程退出运行之后,PID就会回收,可能之后创建的进程会分配这个PID
  • Parent Process ID(PPID)
    字面意思,父进程的PID
  • Process Group ID(PGID)
    PGID就是进程所属的Group的Leader的PID,如果PGID=PID,那么该进程是Group Leader
  • Session ID(SID)
    和PGID非常相似,SID就是进程所属的Session Leader的PID,如果SID==PID,那么该进程是session leader

杀掉进程 

kill -9 [PID编码]  //进程ID

 第一个系统调用getpid

查看运行起来后,才会使用系统调用接口,才获取进程中的标识

注意:

=========================================================================

根目录下有一个文件proc是一个内存级的文件

注意 

下面的这个数字目录其实是进程编号就是刚刚在运行代码的PID

就可以找到

ls -d  //如果查看的是一个目录就只显示目录名不显示子文件 

 

exe是进程对应的可执行文件(磁盘)

进程是加载磁盘上exe

 如果在运行中删除exe,就是已经写入内存中了,将exe删除会发生什么?

 另一种调用方式(了解)

getppid()

探讨一下

如果我们结束这个进程会发生什么呢? 

总结:

在命令行上启动的进程,一般它的父进程没有特殊情况的话,都是bash

父bash交给子bash去执行,出问题没有影响到父进程

比如写了个代码是错误的,父bash创建子bash执行,直接报错此时子bash搞砸了,子bash结束了返回报错问题,但是父bash还是可以用

Linux如何创建子进程(见见🐖跑)

man 2 fork      //系统调用手册

学习返回值

这个id有两个值(知道就行后面会解释)

两个死循环可以同时执行就证明了有两个进程

并发式编程 不同系统和语言不一样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值