Linux设置进程名称(标题) ( 7) -【Linux通信架构系列 】

2023-11-09

系列文章目录

C++技能系列
Linux通信架构系列
C++高性能优化编程系列
深入理解软件架构设计系列
高级C++并发线程编程

期待你的关注哦!!!
在这里插入图片描述

现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.

@TOC
nginx.c


//整个程序入口函数放这里
/*
王健伟老师 《Linux C++通讯架构实战》
商业级质量的代码,完整的项目,帮你提薪至少10K
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h> 
#include <errno.h>
#include <arpa/inet.h>

#include "ngx_macro.h"         //各种宏定义
#include "ngx_func.h"          //各种函数声明
#include "ngx_c_conf.h"        //和配置文件处理相关的类,名字带c_表示和类有关
#include "ngx_c_socket.h"      //和socket通讯相关
#include "ngx_c_memory.h"      //和内存分配释放等相关
#include "ngx_c_threadpool.h"  //和多线程有关

//本文件用的函数声明
static void freeresource();

//和设置标题有关的全局量
size_t  g_argvneedmem=0;        //保存下这些argv参数所需要的内存大小
size_t  g_envneedmem=0;         //环境变量所占内存大小
int     g_os_argc;              //参数个数 
char    **g_os_argv;            //原始命令行参数数组,在main中会被赋值
char    *gp_envmem=NULL;        //指向自己分配的env环境变量的内存,在ngx_init_setproctitle()函数中会被分配内存
int     g_daemonized=0;         //守护进程标记,标记是否启用了守护进程模式,0:未启用,1:启用了

//socket/线程池相关
CSocekt      g_socket;          //socket全局对象
CThreadPool  g_threadpool;      //线程池全局对象

//和进程本身有关的全局量
pid_t   ngx_pid;                //当前进程的pid
pid_t   ngx_parent;             //父进程的pid
int     ngx_process;            //进程类型,比如master,worker进程等

sig_atomic_t  ngx_reap;         //标记子进程状态变化[一般是子进程发来SIGCHLD信号表示退出],sig_atomic_t:系统定义的类型:访问或改变这些变量需要在计算机的一条指令内完成
                                   //一般等价于int【通常情况下,int类型的变量通常是原子访问的,也可以认为 sig_atomic_t就是int类型的数据】                                   

//程序主入口函数----------------------------------
int main(int argc, char *const *argv)
{   
    //time_t mytime = time(NULL);
    //printf("time = %u",mytime);
    //exit(0);
    //#ifdef _POSIX_THREADS 
    //    printf("henhao");
    //#endif    
    //exit(0);
    //printf("unsigned long sizeof=%d",sizeof(unsigned long));
    //printf("htonl(100)=%d",htonl(100));
    //printf("ntohl(htonl(100)=%d",ntohl(htonl(100)));
    //exit(0);
    //printf("EAGAIN=%d,EWOULDBLOCK=%d,EINTR=%d",EAGAIN,EWOULDBLOCK,EINTR);
    //ssize_t n = -1;
    //printf("ssize_t n = %d\n",n);
    //exit(0);
    int exitcode = 0;           //退出代码,先给0表示正常退出
    int i;                      //临时用
    //CMemory *p_memory;

    //(1)无伤大雅也不需要释放的放最上边    
    ngx_pid    = getpid();      //取得进程pid
    ngx_parent = getppid();     //取得父进程的id 
    //统计argv所占的内存
    g_argvneedmem = 0;
    for(i = 0; i < argc; i++)  //argv =  ./nginx -a -b -c asdfas
    {
        g_argvneedmem += strlen(argv[i]) + 1; //+1是给\0留空间。
    } 
    //统计环境变量所占的内存。注意判断方法是environ[i]是否为空作为环境变量结束标记
    for(i = 0; environ[i]; i++) 
    {
        g_envneedmem += strlen(environ[i]) + 1; //+1是因为末尾有\0,是占实际内存位置的,要算进来
    } //end for

    g_os_argc = argc;           //保存参数个数
    g_os_argv = (char **) argv; //保存参数指针

    //全局量有必要初始化的
    ngx_log.fd = -1;                  //-1:表示日志文件尚未打开;因为后边ngx_log_stderr要用所以这里先给-1
    ngx_process = NGX_PROCESS_MASTER; //先标记本进程是master进程
    ngx_reap = 0;                     //标记子进程没有发生变化
   
    //(2)初始化失败,就要直接退出的
    //配置文件必须最先要,后边初始化啥的都用,所以先把配置读出来,供后续使用 
    CConfig *p_config = CConfig::GetInstance(); //单例类
    if(p_config->Load("nginx.conf") == false) //把配置文件内容载入到内存            
    {   
        ngx_log_init();    //初始化日志
        ngx_log_stderr(0,"配置文件[%s]载入失败,退出!","nginx.conf");
        //exit(1);终止进程,在main中出现和return效果一样 ,exit(0)表示程序正常, exit(1)/exit(-1)表示程序异常退出,exit(2)表示表示系统找不到指定的文件
        exitcode = 2; //标记找不到文件
        goto lblexit;
    }
    //(2.1)内存单例类可以在这里初始化,返回值不用保存
    CMemory::GetInstance();	
        
    //(3)一些必须事先准备好的资源,先初始化
    ngx_log_init();             //日志初始化(创建/打开日志文件),这个需要配置项,所以必须放配置文件载入的后边;     
        
    //(4)一些初始化函数,准备放这里        
    if(ngx_init_signals() != 0) //信号初始化
    {
        exitcode = 1;
        goto lblexit;
    }        
    if(g_socket.Initialize() == false)//初始化socket
    {
        exitcode = 1;
        goto lblexit;
    }

    //(5)一些不好归类的其他类别的代码,准备放这里
    ngx_init_setproctitle();    //把环境变量搬家

    //------------------------------------
    //(6)创建守护进程
    if(p_config->GetIntDefault("Daemon",0) == 1) //读配置文件,拿到配置文件中是否按守护进程方式启动的选项
    {
        //1:按守护进程方式运行
        int cdaemonresult = ngx_daemon();
        if(cdaemonresult == -1) //fork()失败
        {
            exitcode = 1;    //标记失败
            goto lblexit;
        }
        if(cdaemonresult == 1)
        {
            //这是原始的父进程
            freeresource();   //只有进程退出了才goto到 lblexit,用于提醒用户进程退出了
                              //而我现在这个情况属于正常fork()守护进程后的正常退出,不应该跑到lblexit()去执行,因为那里有一条打印语句标记整个进程的退出,这里不该限制该条打印语句;
            exitcode = 0;
            return exitcode;  //整个进程直接在这里退出
        }
        //走到这里,成功创建了守护进程并且这里已经是fork()出来的进程,现在这个进程做了master进程
        g_daemonized = 1;    //守护进程标记,标记是否启用了守护进程模式,0:未启用,1:启用了
    }

    //(7)开始正式的主工作流程,主流程一致在下边这个函数里循环,暂时不会走下来,资源释放啥的日后再慢慢完善和考虑    
    ngx_master_process_cycle(); //不管父进程还是子进程,正常工作期间都在这个函数里循环;
        
    //--------------------------------------------------------------    
    //for(;;)    
    //{
    //    sleep(1); //休息1秒        
    //    printf("休息1秒\n");        
    //}
      
    //--------------------------------------
lblexit:
    //(5)该释放的资源要释放掉
    ngx_log_stderr(0,"程序退出,再见了!");
    freeresource();  //一系列的main返回前的释放动作函数
    //printf("程序退出,再见!\n");    
    return exitcode;
}

//专门在程序执行末尾释放资源的函数【一系列的main返回前的释放动作函数】
void freeresource()
{
    //(1)对于因为设置可执行程序标题导致的环境变量分配的内存,我们应该释放
    if(gp_envmem)
    {
        delete []gp_envmem;
        gp_envmem = NULL;
    }

    //(2)关闭日志文件
    if(ngx_log.fd != STDERR_FILENO && ngx_log.fd != -1)  
    {        
        close(ngx_log.fd); //不用判断结果了
        ngx_log.fd = -1; //标记下,防止被再次close吧        
    }
}

ngx_global.h

#include <signal.h> 

#include "ngx_c_socket.h"
#include "ngx_c_threadpool.h"

//一些比较通用的定义放在这里,比如typedef定义
//一些全局变量的外部声明也放在这里

//类型定义----------------

//结构定义
typedef struct _CConfItem
{
	char ItemName[50];
	char ItemContent[500];
}CConfItem,*LPCConfItem;

//和运行日志相关 
typedef struct
{
	int    log_level;   //日志级别 或者日志类型,ngx_macro.h里分0-8共9个级别
	int    fd;          //日志文件描述符

}ngx_log_t;


//外部全局量声明
extern size_t        g_argvneedmem;
extern size_t        g_envneedmem; 
extern int           g_os_argc; 
extern char          **g_os_argv;
extern char          *gp_envmem; 
extern int           g_daemonized;
extern CSocekt       g_socket;  
extern CThreadPool   g_threadpool;

extern pid_t         ngx_pid;
extern pid_t         ngx_parent;
extern ngx_log_t     ngx_log;
extern int           ngx_process;   
extern sig_atomic_t  ngx_reap;   

ngx_func.h

//函数声明放在这个头文件里-------------------------------------------

#ifndef __NGX_FUNC_H__
#define __NGX_FUNC_H__

//字符串相关函数
void   Rtrim(char *string);
void   Ltrim(char *string);

//设置可执行程序标题相关函数
void   ngx_init_setproctitle();
void   ngx_setproctitle(const char *title);

//和日志,打印输出有关
void   ngx_log_init();
void   ngx_log_stderr(int err, const char *fmt, ...);
void   ngx_log_error_core(int level,  int err, const char *fmt, ...);
u_char *ngx_log_errno(u_char *buf, u_char *last, int err);
u_char *ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...);
u_char *ngx_slprintf(u_char *buf, u_char *last, const char *fmt, ...);
u_char *ngx_vslprintf(u_char *buf, u_char *last,const char *fmt,va_list args);

//和信号/主流程相关相关
int    ngx_init_signals();
void   ngx_master_process_cycle();
int    ngx_daemon();
void   ngx_process_events_and_timers();


#endif  

ngx_setproctitle.cxx

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>  //env
#include <string.h>

#include "ngx_global.h"

//设置可执行程序标题相关函数:分配内存,并且把环境变量拷贝到新内存中来
void ngx_init_setproctitle()
{   
    //这里无需判断penvmen == NULL,有些编译器new会返回NULL,有些会报异常,但不管怎样,如果在重要的地方new失败了,你无法收场,让程序失控崩溃,助你发现问题为好; 
    gp_envmem = new char[g_envneedmem]; 
    memset(gp_envmem,0,g_envneedmem);  //内存要清空防止出现问题

    char *ptmp = gp_envmem;
    //把原来的内存内容搬到新地方来
    for (int i = 0; environ[i]; i++) 
    {
        size_t size = strlen(environ[i])+1 ; //不要拉下+1,否则内存全乱套了,因为strlen是不包括字符串末尾的\0的
        strcpy(ptmp,environ[i]);      //把原环境变量内容拷贝到新地方【新内存】
        environ[i] = ptmp;            //然后还要让新环境变量指向这段新内存
        ptmp += size;
    }
    return;
}

//设置可执行程序标题
void ngx_setproctitle(const char *title)
{
    //我们假设,所有的命令 行参数我们都不需要用到了,可以被随意覆盖了;
    //注意:我们的标题长度,不会长到原始标题和原始环境变量都装不下,否则怕出问题,不处理
    
    //(1)计算新标题长度
    size_t ititlelen = strlen(title); 

    //(2)计算总的原始的argv那块内存的总长度【包括各种参数】    
    size_t esy = g_argvneedmem + g_envneedmem; //argv和environ内存总和
    if( esy <= ititlelen)
    {
        //你标题多长啊,我argv和environ总和都存不下?注意字符串末尾多了个 \0,所以这块判断是 <=【也就是=都算存不下】
        return;
    }

    //空间够保存标题的,够长,存得下,继续走下来    

    //(3)设置后续的命令行参数为空,表示只有argv[]中只有一个元素了,这是好习惯;防止后续argv被滥用,因为很多判断是用argv[] == NULL来做结束标记判断的;
    g_os_argv[1] = NULL;  

    //(4)把标题弄进来,注意原来的命令行参数都会被覆盖掉,不要再使用这些命令行参数,而且g_os_argv[1]已经被设置为NULL了
    char *ptmp = g_os_argv[0]; //让ptmp指向g_os_argv所指向的内存
    strcpy(ptmp,title);
    ptmp += ititlelen; //跳过标题

    //(5)把剩余的原argv以及environ所占的内存全部清0,否则会出现在ps的cmd列可能还会残余一些没有被覆盖的内容;
    size_t cha = esy - ititlelen;  //内存总和减去标题字符串长度(不含字符串末尾的\0),剩余的大小,就是要memset的;
    memset(ptmp,0,cha);
    return;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux设置进程名称(标题) ( 7) -【Linux通信架构系列 】 的相关文章

  • 如何将 elf 解释器(ld-linux.so.2/ld-2.17.so)构建为静态库?

    如果我的问题不准确 我深表歉意 因为我没有太多 Linux 相关经验 我目前正在构建一个 Linux 从头开始 主要遵循 linuxfromscratch org 版本的指南 7 3 我遇到了以下问题 当我构建可执行文件时 获取一个称为 E
  • Visual Studio - X11:缺少 DISPLAY 环境变量

    我正在使用 Visual Studio 2019 Enterprise 开发跨平台 Windows Linux x64 GUI 应用程序 在这个 2019 版本中 我们可以使用 Visual Studio调试平台 Windows 本机 和
  • 套接字发送调用被阻塞很长时间

    我每 10 秒在套接字上发送 2 个字节的应用程序数据 阻塞 但发送调用在下面的最后一个实例中被阻塞超过 40 秒 2012 06 13 12 02 46 653417 信息 发送前 2012 06 13 12 02 46 653457 信
  • php_network_getaddresses: getaddrinfo 失败: 名称或服务未知 (0) 连接失败..!

    我正在使用 php 邮件程序功能 但出现以下错误 如何修复它 2016 01 22 06 15 48 SMTP 错误 无法连接到服务器 php network getaddresses getaddrinfo失败 名称或服务未知 0 连接失
  • 为什么 call_usermodehelper 大多数时候都会失败?

    从内核模块中 我尝试使用 call usermodehelper 函数来执行可执行文件 sha1 该可执行文件将文件作为参数并将文件的 SHA1 哈希和写入另一个文件 名为输出 可执行文件完美运行 int result 1 name hom
  • aarch64 Linux 硬浮点或软浮点

    linux系统有arm64 有arm架构armv8 a 如何知道 Debian 运行的是硬浮动还是软浮动 符合 AAPCS64 GNU GCC for armv8仅提供硬浮动aarch64工具链 这与 armv7 a 的 GCC 不同 后者
  • 如何回忆上一个 bash 命令的参数?

    Bash 有没有办法回忆上一个命令的参数 我通常这样做vi file c其次是gcc file c Bash 有没有办法回忆上一个命令的参数 您可以使用 or 调用上一个命令的最后一个参数 Also Alt can be used to r
  • 如何指定配置脚本的包含目录

    我的工作场所有一个 Linux 系统 其中包含相当旧的软件包 并且没有 root 访问权限 我正在从源代码编译我需要的包 prefix somewhere in homedir 我的问题是我只是不知道如何说服配置在特定目录中查找头文件 源码
  • 如何使用 VSCode 调试 Linux 核心转储?

    我故意从我使用 VSCode 编写的 C 应用程序生成核心转储 我不知道如何调试核心转储 有没有人愿意分享这方面的经验 更新 我相信我现在已经可以使用了 我为核心文件创建了第二个调试配置 我需要添加指向生成的转储文件的 coreDumpPa
  • 为什么使用signalfd无法捕获SIGSEGV?

    我的系统是ubuntu 12 04 我将示例修改为man 2 signalfd 并添加sigaddset mask SIGSEGV 在示例中 但我无法得到输出SIGSEGV被生成 这是一个错误吗glibc 源代码片段如下 sigemptys
  • 当在 python linux 中执行命令 os.system() 时,在 python 中给出响应 yes/no

    考虑一个像这样的命令 yum install boto 当我在终端中执行时 要继续 会询问我是 否 我可以像这样用 python 回应它吗 os system yum install boto Next Yes 将通过相同的 python
  • EULA 接受 Bash 脚本

    我有一个尝试安装垃圾箱的脚本 除了 bin 在 more 中打开 EULA 之外 一切正常 在脚本再次开始并自行完成安装之前 您必须手动 ctrl c 退出此 more 实例 因为这更多的是逃离 shell 所以脚本在打开后不知道要运行什么
  • 每个虚拟主机的错误日志?

    在一台运行 Apache 和 PHP 5 的 Linux 服务器上 我们有多个带有单独日志文件的虚拟主机 我们似乎无法分离 phperror log虚拟主机之间 覆盖此设置
  • Linux 上的“软/硬 nofile”是什么意思

    当我尝试在RedHat EL5上安装软件时 我得到了错误 软 硬nofile的期望值是4096 而默认值是1024 我设法增加了这个数字 但我不知道参数是什么 他们指的是软链接和硬链接吗 我改变的方法是 a 修改 etc security
  • 重新链接匿名(未链接但打开)文件

    在 Unix 中 可以创建匿名文件的句柄 例如 使用 creat 创建并打开它 然后使用 unlink 删除目录链接 留下一个带有 inode 和存储的文件 但没有可能的方法重新打开它 此类文件通常用作临时文件 通常这就是 tmpfile
  • 进程如何知道它已收到信号

    如果我错了 请纠正我 以下是我对信号的理解 据我所知 信号生成 和信号传递有2个不同 事物 为了产生信号 操作系统只是在位数组中设置一个位 在过程控制中维护 工艺块 PCB 每一位 对应于特定信号 当设置一个位时 这意味着 该位对应的信号为
  • 删除 Python 中某些操作的 root 权限

    在我的 Python 脚本中 我执行了一些需要 root 权限的操作 我还创建并写入文件 我不想由 root 独占所有 而是由运行我的脚本的用户独占所有 通常 我使用以下命令运行脚本sudo 有办法做到上述吗 您可以使用以下方式在 uid
  • PHP 日志文件颜色

    我正在编写一个 PHP 日志文件类 但我想为写入文件的行添加颜色 我遇到的问题是颜色也会改变终端的颜色 我想要实现的是仅更改写入日志文件的行的颜色 class logClass extends Singleton private funct
  • 在Linux中创建可执行文件

    我计划做的一件事是编写 非常简单的 Perl 脚本 并且我希望能够在不从终端显式调用 Perl 的情况下运行它们 我明白 要做到这一点 我需要授予他们执行权限 使用 chmod 执行此操作非常简单 但它似乎也是一个稍微费力的额外步骤 我想要
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似

随机推荐

  • HDU--1242:Rescue (BFS)

    1 题目源地址 http acm hdu edu cn showproblem php pid 1242 2 易错点 可能存在多个朋友 即多个map 中有多个 r 所以起始点为Angel的位置 最短时间为到达最近的朋友的时间 3 源代码 H
  • Hands-On Hyperledger Fabric——Fabric模块

    文章目录 Fabric模块在系统中的作用 peer模块 orderer模块 Fabric数据安全传输的方式 Fabric模块在系统中的作用 前面我们知道Fabric是由多个模块组成的程序组 peer orderer cryptogen co
  • if-else 判断输出的字符是大写字母、小写字母、数字或者其他类型

    if else判断输出的字符是大写字母 小写字母 数字 或者其他类型 include
  • Unity 接入Facebook 登陆后报错 "所提供的网址不被应用程序所接纳"

    注意 笔者使用的是Facebook SDK for Unity 错误截图 检查Facebook 开发者后台 是否已经针对对应的 平台 配置相关的数据 以安卓为例 软件包名称 Package Name 顾名思义 就是打包出来的包名 默认活动类
  • v-loading的使用(ElementUI)

    前言 需要获取后端接口数据到页面上进行显示 所以在请求发起至数据渲染页面的这段时间 为页面提供一个 loading 加载是极为必要的 1 区域加载 以 table 表格为例 使用 v loading 为其绑定一个布尔值 true false
  • 定制Android版本的chromium之笔记

    在前面的两篇文章中 分别介绍了如何下载Google Chromium源码 以及编译Android版本的chromium浏览器 准备知识 在实际的开发中 如果直接在chrome的源码上修改代码 既费时也费力 在github找了一个可以直接用
  • java记录操作日志

    记录 logPointCut 方法只是用于定义切点 指定了哪些方法会被拦截 而获取方法上的 OperateLog 注解是为了在切面逻辑中判断是否需要记录操作日志 这两者是配合使用的 前者确定拦截的位置 后者确定在拦截的位置上是否执行操作日志
  • 大神之路-起始篇

    欢迎关注 全栈工程师修炼指南 公众号 点击 下方卡片 即可关注我哟 设为 星标 每天带你 基础入门 到 进阶实践 再到 放弃学习 涉及 企业运维 网络安全 应用开发 物联网 人工智能 大数据 学习知识 花开堪折直须折 莫待无花空折枝 作者主
  • DDOS网络层攻击防御

    TCP类报文攻击防御 目录 TCP类报文攻击防御 TCP交互过程 SYN Flood攻击 特点 概念 攻击原理 防御原理 一 针对虚假源 二 针对真实源 SYN ACK Flood攻击 攻击原理 防御原理 ACK Flood攻击 定义 攻击
  • ES6模块化语法

    定义 每个js 文件都是一个独立的模块 导入其他模块成员使用 import 关键字 export 命令用于规定模块的对外接口 基本语法 默认导入和导出 按需导入和导出 直接导入并执行模块中的额代码 1 默认语法 默认导出格式 export
  • MMSegmentation V0.27.0训练与推理自己的数据集(二)

    MMSegmentation 算法库目录结构的主要部分 mmsegmentation configs 配置文件 base 基配置文件 datasets 数据集相关配置文件 models 模型相关配置文件 schedules 训练日程如优化器
  • Pytorch resnet花朵识别(5种花)附完整代码

    notebook运行结果图 随机从各种花的图片集中抽取一定数量的图片 因为设备限制 用所有的图片 图片太多 如果用cpu跑太慢了 用gpu太多图片会out of memory 所以用小部分图片 了解方法就好了 重写dataset类 显示图片
  • mysql order by和group,where的执行顺序

    Mysql ORDER BY详解 0 索引 1 概述 2 索引扫描排序和文件排序简介 3 索引扫描排序执行过程分析 4 文件排序 5 补充说明 6 参考资料 1 概述 MySQL有两种方式可以实现ORDER BY 1 通过索引扫描生成有序的
  • 解决调试时候出现的“Encountered an improper argument”错误

    今天分享一个我们在调试时候出现的一个错误 同时这个错误让我的工程也崩了好几十次 错误 首先 我们看一下这个错误的提示框图 其错误提示为 Encountered an improper argument 翻译过来就是遇到不恰当的争论 错误原因
  • 多线程(七)锁策略 (乐观锁,悲观锁,读写锁,自旋锁,可重入锁)

    目录 一 乐观锁和悲观锁 1 乐观锁的理解 2 悲观锁的理解 二 读写锁 1 什么是读写锁 2 读写锁的三种状态 3 读写锁的实现 三 公平锁和非公平锁 四 可重入锁 1 可重入锁 2 可重入锁 VS 自旋锁 五 cas实现和synchro
  • 【java】id非自增的表怎么将数据批量插入数据库

    目录 示例 实体 service层 实现层 mapper mapper xml 技术框架 springboot dubbo mybatis plus id非自增的表怎么将数据批量插入数据库 mapper mapper xml都要改 示例 添
  • conda 导出环境/导入环境/导出base环境以及踩坑

    conda 导出环境 导入环境 导出base环境 参考链接 https blog csdn net shunaoxi2313 article details 92003710 conda的虚拟环境真的非常实用 尤其是对于大的深度学习项目 给
  • Longest Consecutive Sequence

    Given an unsorted array of integers find the length of the longest consecutive elements sequence For example Given 100 4
  • Java实现 LeetCode 704 二分查找(三种解法详解)

    二分查找常见三种解法详解 1 二分法 基础版 左闭右闭区间 2 二分法 改进版 左闭右开区间 3 二分法 平衡版 左闭右开区间 704 二分查找 给定一个 n 个元素有序的 升序 整型数组 nums 和一个目标值 target 写一个函数搜
  • Linux设置进程名称(标题) ( 7) -【Linux通信架构系列 】

    系列文章目录 C 技能系列 Linux通信架构系列 C 高性能优化编程系列 深入理解软件架构设计系列 高级C 并发线程编程 期待你的关注哦 现在的一切都是为将来的梦想编织翅膀 让梦想在现实中展翅高飞 Now everything is fo