进程概要

本文介绍了C程序内存布局中的跳转机制,包括函数内跳转和线程内跳转,通过示例程序展示了如何使用setjmp和longjmp进行非局部跳转,并探讨了跳转后局部变量的状态。同时,文章还讲解了进程资源管理,列出了各种进程资源限制及其含义,并提供了打印资源限制的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C程序内存布局


进程退出函数
void _exit(int status);
void _Exit(int status);
voit exit(int status);
void atexit(void (*func)());  // 注册进程退出时调用的函数

函数内跳转
使用goto语句即可实现函数内跳转,此种跳转只需修改指令指针,不需修改堆栈指针。

线程内跳转
跳转函数:
#include <setjmp.h>

int setjmp(jmp_buf env);  // 第一次返回0,调用longjmp跳转至此处时返回longjmp所设置的参数
void longjmp(jmp_buf env, int res); // 跳转至setjmp处
进行非局部跳转时,需修改指令指针和堆栈指针,指令指针用于重新定位程序执行位置,堆栈指针用于恢复执行环境。
有一个问题?在longjmp之后,函数栈是否会完全恢复到第一次调用setjmp时的样子(亦即,栈内的局部变量是否会回滚)。标准并未对此作答,但我们却可以用volatile关键字来保证局部变量不回滚;那如果我们就想回滚怎么办?没办法!
示例程序:
#include <unistd.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static jmp_buf jmpbuffer;

void jumpByCondition(char* str);

int main(int argc, char *argv[])
{
    const int s_maxBuffer = 256;
    char buff[s_maxBuffer];
    int val = 0;
    register int regVal = 0;
    volatile int volVal = 0;

    if (setjmp(jmpbuffer) != 0)
    {
        printf("error val=%d, regVal=%d, volVal=%d\n", val, regVal, volVal);
        exit(1);
    }

    while (fgets(buff, s_maxBuffer, stdin))
    {
        ++val; ++regVal; ++volVal;
        jumpByCondition(buff);
    }
    
    exit(0);
}

void jumpByCondition(char* str)
{
    if (strstr(str, "jump") != NULL )
    {
        longjmp(jmpbuffer, 1);
    }
    else
    {
        int len = strlen(str);
        if (len - 1 > 0 && str[len - 1] == '\n')
            str[len - 1] = '\0';
        puts(str);
    }
}

进程资源
函数:
#include <sys/resource.h>

int getrlimit(int resource, struct rlimit *pLimit); // 成功返回0,出错返回非0
int setrlimit(int resource, const struct rlimt *pLimit); // 成功返回0,出错返回非0

struct rmlit
{
     int rlim_cur; // 软限制(当前限制)
     int rlim_max; // 硬限制(最大限制)
};
进程资源常值意义
RLIMIT_AS进程可用存储区的最大长度
RLIMIT_CORE
core文件的最大字节数,若为0则表示阻止创建core文件
RLIMIT_CPUCPU时间的最大量值(单位秒),若超过此限制则向进程发送SIGXCPU信号
RLIMIT_DATA初始化数据段、BSS段、堆的总长度限制
RLIMIT_FSIZE可创建的文件的最大长度,超过此长度时向进程发送SIGXFSZ信号
RLIMIT_LOCKS一个进程可持有文件锁的最大数量
RLIMIT_MEMLOCK进程使用mlock可锁定的最大字节长度
RLIMIT_NOFILE进程能打开的最大文件数
RLIMIT_NPPROC每个用户ID可拥有的最大子进程数
RLIMIT_RSS最大驻内存集的字节长度
RLIMIT_SBSIZE用户在任一给定时间内可以占用的套接字缓冲区的最大长度
RLIMIT_STACK栈的字节长度
RLIMIT_VMEMRLIMIT_AS的同意词
打印进程资源限制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>

#define PRINT_RLIMIT(res) printrlimit(#res, res)
void printrlimit(const char* name, int resID);

int main(int argc, char *argv[])
{
     PRINT_RLIMIT(RLIMIT_AS);
     PRINT_RLIMIT(RLIMIT_CORE);
     PRINT_RLIMIT(RLIMIT_CPU);
     PRINT_RLIMIT(RLIMIT_DATA);
     PRINT_RLIMIT(RLIMIT_FSIZE);
     PRINT_RLIMIT(RLIMIT_LOCKS);
     PRINT_RLIMIT(RLIMIT_MEMLOCK);
     PRINT_RLIMIT(RLIMIT_NOFILE);
     #ifdef RLIMIT_NPPROC
     PRINT_RLIMIT(RLIMIT_NPPROC);
     #endif
     PRINT_RLIMIT(RLIMIT_RSS);
     #ifdef RLIMIT_SBSIZE
     PRINT_RLIMIT(RLIMIT_SBSIZE);
     #endif
     PRINT_RLIMIT(RLIMIT_STACK);
     #ifdef RLIMIT_VMEM
     PRINT_RLIMIT(RLIMIT_VMEM);
     #endif
     exit(0);
}

void printrlimit(const char* name, int resID)
{
     struct rlimit limit;
     if (getrlimit(resID, &limit) != 0)
     {
          printf("getrlimit error. resid=%d\n", resID);
          exit(1);
     }

     printf("%14s    curlim:", name);
     if (limit.rlim_cur == RLIM_INFINITY)
     {
          printf("(infinity)");
     }
     else
     {
          printf("%10ld", limit.rlim_cur);
     }

     printf("    maxlim:");
     if (limit.rlim_max == RLIM_INFINITY)
     {
          printf("(infinity)");
     }
     else
     {
          printf("%10ld", limit.rlim_max);
     }
     putchar('\n');
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值