sec_log学习

本文深入探讨了N7100设备中内核日志(kernel log)的保存机制,包括日志缓冲区初始化过程、环形缓冲区的实现方式以及对上一次内核消息(kmsg)的保存方法。

学习了下 n7100代码中对kernel log保存代码:

kernel log保存:

1. init.setup 段初始化:

sec_log有如下实现

__setup("sec_log=", sec_log_setup);

说明如下
/*
 * Example usage: sec_log=256K@0x45000000
 * In above case, log_buf size is 256KB and its base address is
 * 0x45000000 physically. Actually, *(int *)(base - 8) is log_magic and
 * *(int *)(base - 4) is log_ptr. So we reserve (size + 8) bytes from
 * (base - 8).
 */


#define __setup(str, fn)                    \
    __setup_param(str, fn, fn, 0)
在内核booting过程中如果对比发现str=a的cmd会调用对应的fn(a)

具体实现如下


vmlinux.lds.h
#define INIT_SETUP(initsetup_align)                    \
        . = ALIGN(initsetup_align);                \
        VMLINUX_SYMBOL(__setup_start) = .;            \
        *(.init.setup)                        \
        VMLINUX_SYMBOL(__setup_end) = .;
#define INIT_CALLS                            \
        VMLINUX_SYMBOL(__initcall_start) = .;            \
        INITCALLS                        \
        VMLINUX_SYMBOL(__initcall_end) = .;


#define INIT_DATA_SECTION(initsetup_align)                \
    .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {        \
        INIT_DATA                        \
        INIT_SETUP(initsetup_align)                \
        INIT_CALLS                        \
        CON_INITCALL                        \
        SECURITY_INITCALL                    \
        INIT_RAM_FS                        \
    }


对于__setup()定义的:
start_kernel()-->     setup_arch(&command_line);-->parse_early_param();
对于moudle_init定义的:
start_kernel() --> rest_init(); --> kernel_init() --> do_basic_setup() --> do_init_calls()
其中kenrel_init中:
static int __init kernel_init(void * unused)
{
    /*
     * Wait until kthreadd is all set-up.
     */
    wait_for_completion(&kthreadd_done);
    /*
     * init can allocate pages on any node
     */
    set_mems_allowed(node_states[N_HIGH_MEMORY]);
    /*
     * init can run on any cpu.
     */
    set_cpus_allowed_ptr(current, cpu_all_mask);

    cad_pid = task_pid(current);

    smp_prepare_cpus(setup_max_cpus);

    do_pre_smp_initcalls();
    lockup_detector_init();

    smp_init(); // enable multi-core
    sched_init_smp();

    do_basic_setup(); //init_machine也在这里调用
    ......
    init_post();//这里调用free_initmem将initmem释放回收:

        totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
                        __phys_to_pfn(__pa(__init_end)),
                        "init");
}



2. 对于ringbuffer 循环写的实现:
static inline void emit_sec_log_char(char c)
{
    if (sec_log_buf && sec_log_ptr) {
        sec_log_buf[*sec_log_ptr & (sec_log_size - 1)] = c;
        (*sec_log_ptr)++;
    }
}
这里& (sec_log_size - 1)  保证了在sec_log_size范围内 循环写(这要保证sec_log_size为1左移整数位的大小)

3.对上一次kmsg的保存:
static void __init sec_log_save_old(void)
{
    /* provide previous log as last_kmsg */
    last_kmsg_size =
        min((unsigned)(1 << CONFIG_LOG_BUF_SHIFT), *sec_log_ptr);
    last_kmsg_buffer = (char *)alloc_bootmem(last_kmsg_size);

    if (last_kmsg_size && last_kmsg_buffer) {
        unsigned i;
        for (i = 0; i < last_kmsg_size; i++)
            last_kmsg_buffer[i] =
                sec_log_buf[(*sec_log_ptr - last_kmsg_size +
                     i) & (sec_log_size - 1)];

        pr_info("%s: saved old log at %d@%p\n",
            __func__, last_kmsg_size, last_kmsg_buffer);
    } else
        pr_err("%s: failed saving old log %d@%p\n",
               __func__, last_kmsg_size, last_kmsg_buffer);
}
这里CONFIG_LOG_BUF_SHIFT是系统默认的比如 17 那么系统kmsg buffer默认为128K
不管sec_log_size多大,我们可以只保存lastmsg最大128K,其余的丢弃。
last_kmsg_size =
        min((unsigned)(1 << CONFIG_LOG_BUF_SHIFT), *sec_log_ptr);
这样如果sec_log_ptr跑的长度大于128K 我们只要128K 如果有效长度小于128K 我们取有效长度。


finish /clear !钢的弹性模量,密度,泊松比 /prep7 mp,ex,1,2.06e11 mp,dens,1,7850 mp,prxy,1,0.31 et,1,beam188 !网格节点 k,1,1.2,0,-0.9625 k,2,1.8,0,-0.6625 k,3,2.4,0,-0.0225 k,4,3,0,0.9375 k,5,2.4,0,0.6 k,6,1.8,0,0.3375 k,7,1.2,0,0.15 k,8,0.6,0,0.0375 k,9,0.6,0,-1.1625 !连线 l,1,8 l,1,7 l,2,7 l,2,6 l,3,6 l,3,5 l,7,8 l,6,7 l,5,6 l,4,5 l,3,4 l,2,3 l,1,2 l,1,9 ! 截面定义(矩形截面,宽50mm,高100mm,初始固定) sectype,1,beam,rect secoffset,cent ! 形心对齐轴线,无偏心 secdata,0.05,0.1 ! 宽=0.05m,高=0.1m(50mm×100mm) ! 属性分配+网格划分 allsel,all latt,1,,1,,,,1 ! 所有线(曲线+直线)分配:单元1+材料1+截面1 lesize,all,0.1 ! 单元长度0.1m lmesh,all ! 划分网格 ! 显示关键点编号(验证建模正确性) /PNUM,KPOI,1 /VIEW,2,0,1,0 ! 俯视X-Z平面,清晰查看 PLOT,LINE /REPLOT /solu antype,static ! 静态分析 acel,0,0,9.81 ! 重力沿-Z方向(适配X-Z平面结构,向下为-Z) ! 获取所有关键点对应的节点编号 *get,node1,node,,num,min ! 初始化变量(避免未定义报错) nslk,s,kp,1 ! 选择与关键点1关联的所有节点 *get,node1,node,,num,min ! 提取选中节点中编号最小的(即关键点1直接关联的节点) allsel,all ! 取消选择,恢复全选 *get,node2,node,,num,min nslk,s,kp,2 *get,node2,node,,num,min allsel,all *get,node3,node,,num,min nslk,s,kp,3 *get,node3,node,,num,min allsel,all *get,node4,node,,num,min nslk,s,kp,4 *get,node4,node,,num,min allsel,all *get,node5,node,,num,min nslk,s,kp,5 *get,node5,node,,num,min allsel,all *get,node6,node,,num,min nslk,s,kp,6 *get,node6,node,,num,min allsel,all *get,node7,node,,num,min nslk,s,kp,7 *get,node7,node,,num,min allsel,all *get,node8,node,,num,min nslk,s,kp,8 *get,node8,node,,num,min allsel,all *get,node9,node,,num,min nslk,s,kp,9 *get,node9,node,,num,min allsel,all !固定边界:4-8点 + 9点 全约束(稳定支撑) d,node8,all,0 d,node9,all,0 ! 设计变量定义 *dim,kp_x,array,3,3 *dim,kp_z,array,3,3 ! KP1 kp_x(1,1)=1.2 $ kp_x(1,2)=0.84 $ kp_x(1,3)=1.56 kp_z(1,1)=-0.9625 $ kp_z(1,2)=-1.2 $ kp_z(1,3)=-0.7 ! KP2 kp_x(2,1)=1.8 $ kp_x(2,2)=1.26 $ kp_x(2,3)=2.34 kp_z(2,1)=-0.6625 $ kp_z(2,2)=-0.9 $ kp_z(2,3)=-0.4 ! KP3 kp_x(3,1)=2.4 $ kp_x(3,2)=1.68 $ kp_x(3,3)=3.12 kp_z(3,1)=-0.0225 $ kp_z(3,2)=-0.3 $ kp_z(3,3)=0.25 ! 截面变量定义 *dim,sec_var,array,2,3 sec_var(1,1)=0.05 $ sec_var(1,2)=0.03 $ sec_var(1,3)=0.1 sec_var(2,1)=0.1 $ sec_var(2,2)=0.05 $ sec_var(2,3)=0.15 ! 注册设计变量 OPVAR,kp_x(1,1),DESV,kp_x(1,2),kp_x(1,3) ! KP1-X OPVAR,kp_z(1,1),DESV,kp_z(1,2),kp_z(1,3) ! KP1-Z OPVAR,kp_x(2,1),DESV,kp_x(2,2),kp_x(2,3) ! KP2-X OPVAR,kp_z(2,1),DESV,kp_z(2,2),kp_z(2,3) ! KP2-Z OPVAR,kp_x(3,1),DESV,kp_x(3,2),kp_x(3,3) ! KP3-X OPVAR,kp_z(3,1),DESV,kp_z(3,2),kp_z(3,3) ! KP3-Z OPVAR,sec_var(1,1),DESV,sec_var(1,2),sec_var(1,3) ! 截面宽 OPVAR,sec_var(2,1),DESV,sec_var(2,2),sec_var(2,3) ! 截面高 ! 目标函数:最小化结构总质量 *dim,elem_vol,array,1000 ! 定义数组存储每个单元的体积 *do,i,1,nelem ! 循环遍历所有单元(nelem是ANSYS内置变量,自动获取单元总数) elem_vol(i) = volu(i) ! 直接读取第i个单元的体积(volu(i)是单元i的体积内置变量,单位m³) *enddo *sum,vol_total,elem_vol ! 对所有单元体积求和,得到总体积vol_total(m³) total_mass = vol_total * 7850 ! 总质量=总体积×密度(7850 kg/m³,单位kg) OPVAR,total_mass,OBJ,MIN ! 注册目标函数:最小化总质量 !保存初始求解结果(优化前基准) ! 直接使用截面尺寸设计变量的乘积来定义面积约束,无需*GET命令 OPVAR,sec_var(1,1)*sec_var(2,1),CVAL,,0.005 ! 约束:宽度 * 高度 ≥ 0.005 m² ! 挠度约束:1、2、3点Z向挠度的RMS≤0.1mm(0.0001m) *dim,node_list,array,3 ! 定义节点编号数组(存储1、2、3号节点) *dim,delta_z,array,3 ! 定义挠度数组(存储对应节点的Z向挠度) ! 赋值节点编号(对应node1、node2、node3,与你的模型一致) node_list(1) = node1 node_list(2) = node2 node_list(3) = node3 ! 核心:用*VGET批量提取Z向挠度 *VGET,delta_z(1),NODE,node_list(1),U,Z ! 提取节点1的Z向挠度(m) *VGET,delta_z(2),NODE,node_list(2),U,Z ! 提取节点2的Z向挠度(m) *VGET,delta_z(3),NODE,node_list(3),U,Z ! 提取节点3的Z向挠度(m) ! 计算RMS(均方根,取绝对值避免正负抵消,约束逻辑不变) RMS = SQRT(ABS(delta_z(1))**2 + ABS(delta_z(2))**2 + ABS(delta_z(3))**2) / SQRT(3) OPVAR,RMS,CVAL,,0.0001 ! 注册约束:RMS≤0.0001m(0.1mm) ! 3.2 强度约束:最大von Mises应力≤156.67MPa(235/1.5,安全系数1.5) *dim,elem_sig,array,1000 ! 定义数组存储每个单元的von Mises应力 *do,i,1,nelem ! 循环遍历所有单元(nelem=ANSYS内置变量,自动获取单元总数) elem_sig(i) = SIGM(i,1) ! 直接读取第i个单元的von Mises应力(单位:Pa,无标签冲突) *enddo *VMAX,sigma_max,elem_sig(1),nelem ! 从数组中提取最大应力值(sigma_max=最大应力,Pa) sigma_max_mpa = sigma_max/1e6 ! 转换为MPa(1MPa=1e6Pa) OPVAR,sigma_max_mpa,CVAL,,156.67 ! 注册约束:最大应力≤156.67MPa ! 优化控制参数 OPTYPE,ZERO ! 零阶优化(结构优化首选,收敛稳定) NSUB,100 ! 最大迭代次数(足够收敛) CONV,0.001 ! 收敛精度(设计变量变化≤0.1%) OUTPUT,opti_log,,1 ! 每1步输出日志,便于监控 solve /POST1 ! 获取最大等效应力 SET, LAST allsel,all *get,max_stress,SECR,,S,EQV,MAX ! 获取节点2,3,4,5的Z向位移 *get,uz_node2,NODE,14,U,z *get,uz _node5,NODE,37,U,z *get,uz_node8,NODE,54,U,z *get,uz_node11,NODE,79,U,z !截面面积 *DIM, sec_area, ARRAY, 7 pi=3.14159 sec_area(1) = pi*(0.03*a2)**2-pi*(0.01*a1)**2 sec_area(2) = pi*(0.03*a4)**2-pi*(0.01*a3)**2 sec_area(3) = pi*(0.03*a6)**2-pi*(0.01*a5)**2 sec_area(4) = pi*(0.03*a8)**2-pi*(0.01*a7)**2 sec_area(5) = pi*(0.03*a10)**2-pi*(0.01*a9)**2 sec_area(6) = pi*(0.03*a12)**2-pi*(0.01*a11)**2 sec_area(7) = pi*(0.03*a14)**2-pi*(0.01*a13)**2 !获得单个节点坐标 *get,x8,node,1,loc,x *get,z8,node,1,loc,z *get,x9,node,26,loc,x *get,z9,node,26,loc,z *get,x10,node,47,loc,x *get,z10,node,47,loc,z ! 计算位移均方根 uz_geo_mean =(((uz_node2)**2+(uz_node5)**2+(uz_node8)**2+(uz_node11)**2)*0.25)**0.5 ! 获取总质量 *GET,ELEM_COUNT,ELEM,0,COUNT V_total=0 *DO,q,1,ELEM_COUNT *get,ELEM_V,ELEM,q,VOLU V_total=V_total+ELEM_V *ENDDO total_mass=V_total*7850 total_gravity=total_mass*9.81 ! ============= 输出优化所需结果 ============ *create,OUT,mac *CFOPEN, results, txt ! 输出格式:应力, 位移几何平均值, 质量, 各节点位移, 各截面面积, 节点坐标 *VWRITE, max_stress, uz_geo_mean, total_gravity, uz_node2, uz_node5, uz_node8, uz_node11 (7F20.8) *VWRITE, sec_area(1), sec_area(2), sec_area(3), sec_area(4), sec_area(5), sec_area(6), sec_area(7) (7F20.8) *VWRITE, x8, z8, x9, z9, x10, z10 (6F20.8) *CFCLOSE *end /input,OUT,mac apdl产出的结果点坐标无变化,帮我改进一下apdl的命令
最新发布
11-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值