linux程序设计需要注意的问题

linux程序设计需要注意的问题

  1. socket的服务器第二次启动显示无法bing到对应地址和端口上

    这个使用netstat -anlp 查看对应的端口状态后,发现是TIME_WAIT状态,这个状态是不能连接的,应该如下解决

    int one = 1;
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&one,sizeof(one));
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEPORT,&one,sizeof(one));
    

    设置one=1 就是启用,one=0就是取消

    项目说明:

    SO_REUSEADDR : 设置处在TIME_WAIT的地址可以重复使用.

    SO_REUSEPORT : 设置处在TIME_WAIT的端口可以重复使用.

    注意 : 编写服务器程序的时候,应该都设置这两个选项,如果没有,服务器将不能立刻重起

对程序内存结构和程序存储位置的理解

之前看过许多有关系统中,对内存分配的一些文章,一直一知半解,直到调研一个系统调用,才真正的弄明白是怎么回事.有一个重点就是,这里说的全局数据区,全局,说的不说c++中的全局的概念,如果那样理解很容易感觉模棱两可,这里说的全局说系统看来,不是一个程序的看待,对系统来说,一个程序的全局就是,需要在程序运行前准备好的内存,对于c++中的变量,系统看来只有三种:全局,stack,bss, 其他两个,stack管程序调用,bss指需要,但是运行的时候才能知道内容.加载慢的一个优化手段就是,调整程序,让bss代替data,具体为什么,下文会说,

这个内容想写写来源于对一个系统调用的研究 brk(void* addr), 某些程序加载的时候cpu很高,使用strace -p PID查看以后,发现他一直执行brk这个系统调用.

brk: 调整程序的数据段,把数据段的地址往高地址调整,,,,,这个有啥用?地址段不是应该加载的时候分配好的吗?有的说这个还能分配动态内存,动态内存不是在heep区分配的吗?总之疑点重重.

一般系统中的地址分配都是从低到高, 依次是:

text段 => 存放指令代码,在可执行文件中也由这一部分,系统会把文件中的text端拷贝到内存里

bss段 => 未初始化的全局数据区,一般系统会弄成0,这一部分在可执行文件中是没有的,只是记录一下需要多少这种空间

data数据段 => 这一部分比较特殊,下文会具体说明,可执行文件中可能有也可能没有.

——-> 这有个指针(系统用的,不过用户态可以通过调用修改) _edata

heep堆 => 这是通常 认为 的malloc申请内存的地方,其实也不一定的,下文会说

stack栈地址 => 栈地址,通常的函数调式都会用到的,

==>

==>

3G以上就是内核区了,用户态就别想自由使用了.

brk的功能就是,把 _edata的地址网高出推,往 heap这边推,可以想象,brk把_data往heep推了,heep能分配的空间肯定就少了啊,

对的,是这样的,

有关brk分配内存的说明

c语言中分配内存,当然是使用malloc了,brk分配内存的功能,就是在这里的,glibc对malloc的实现,是如果分配的内存在 126k以内,就使用brk分配,把brk往heep端推一点,多余出来的数据段,返回给用户,用作动态内存,当读写这个内存的时候,就会引发一个 缺页中断 让系统在物理内存里分配段内存.126k以内都用brk,我们平时试试的基本都是使用brk分配的啊,我不信!!,我写个程序给你证明

#include<iostream>
#include<unistd.h>
#include<stdlib.h>
using namespace std;
int main(){
    void*p = malloc(1);
    cout<<p<<endl;
    int a = brk((void*)((char*)p+1000));  //这句调步调影响下次malloc返回的地址
    //int a = brk((void*)((char*)p+1));
    cout<<a<<endl;
    void* d=malloc(1);
    cout<<d<<endl;
    return 0;
}

一开始我使用 brk(p+1) 程序直接崩溃了,后来查了一下两次malloc的地址差,发现一次malloc 已经把_edata的地址上调了460了,如果我在上调,只能调这个数更大的范围了, 这里有个隐含规则 brk 的地址,只能往高处调,不能往低处调,因为已经调好的内存,可能已经分配了,我们私自把地址往下调了,brk也返回成功0,可是程序会直接崩溃.

如果malloc申请的地址超过了126k,才会调用mmap到heap区去申请内存. brk和heap是linux系统调用,malloc是glibc的函数,不是系统调用.

如果_edata只能往上调,那麽,即使malloc把内存释放了,把_edata调下来,也只能依次释放的,可是用户程序不一定这样来,这不就是浪费吗?是的,是这样,用户free,这个地址的一段内存就不能回收了,只有当最高处的地址被free了,才能把_edata调下来,同时通知系统,取消映射.malloc默认没有一个一个字节的向高地址加,而是一次就加许多,这个许多如何知道呢,这个和系统分配的页大小有关,查看办法如下:使用getconf PAGESIZE 查看系统的页大小

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值