Ronan Blog

罗华东的博客 | 向前每多走一步,热爱和勇气就会多一分。

在短视频为王的时代,又见识到了文字带给我的冲击力

2024-10-31 1 min read Society Ronan

不知道从什么时候起,村里的人便开始相信,我能修好很多东西。

经常有人找到我,说电视坏了不能看,于是我摸索着上房顶,抱着信号接收器对着天胡乱寻找。最终也都能让电视正常播放,只是耗时或长或短罢了。有时候是冬天,我把信号接收锅上的雪扫干净,电视就恢复正常了。于是便夸我聪明,接着就老生常谈地讲,他们就是吃了没文化的亏,最后斩钉截铁地说,不读书的人都是傻瓜。

村里有很多老人,几乎都有老年机,但大多数只能记住接听键——只会接听,不会打,更不用说播放音乐之类的了。我坐在家里,听见狗在狂吠,出门打探时见村里的老人在门口尴尬地苦笑,便知道是他(她)的手机或者电视坏了,因为比这更大的事情,就应该找我家里的长辈了。我出门修理,耗时或长或短,也几乎都能修好。有时候问题异常地简单,比如不小心按了静音键,比如不小心切换了模式等。记得有一位老妇人,翻越一个山头蹒跚走来。我问手机的“症状”。回答说每天半夜会自己唱歌,一打它就停,住手了又唱,怀疑缠上了鬼。我一听就知道,是不小心定了个闹钟,但见她表情凝重,强忍着没笑出来,不一会儿定神一想,竟然感觉一阵悲凉。

我无法向他们解释他们遇到的问题是多么的简单。我与他们之间,似乎存在一块无形的屏障。我曾尝试着教会他们一些调整信号接收器的技巧,尝试着教会他们解除静音、调整手机模式的步骤,但最终都无功而返。除了玉米、水稻的种法,其他的他们一概不知,只一个简单得不能再简单的手机按钮也记不住。我没有再强求他们,我害怕让他们觉得我是因为不耐烦而这样。如果这样的误会形成,有些善良的老人,宁愿自己面对半夜的“鬼”,也不愿意再找我。

我其实对如何修理手机一窍不通,如果手机不能开机,我便束手无策。下午在地里收玉米,一位行动不便的老妇人,挪到地里来找我看手机。我久久按住开机键但手机仍然不能开机的时候,我就知道我无能为力了。于是我的眼神不太敢对视她的眼神。我说手机可能坏了,有时间去县城看看。我说这话时,凭借着经验,放轻了语气。99元的手机是她全身上下最值钱的东西,我害怕让她承受太大的打击。我不把话说得太绝对,因为没准,手机明天自己就好了呢。

望着老妇人踉跄远去的背影,我心生难过。我难过,因为那个老妇人,可我不该难过,因为我,也只是一只顶着烈日淌着汗水在玉米地里穿梭的小人儿啊。

摘自:抖音 @小石飞飞

守护进程

2024-10-28 2 min read Linux Ronan

守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。一般采用以d结尾的名字。

1. 进程组

多个进程的集合就是进程组, 这个组中必须有一个组长, 组长就是进程组中的第一个进程,组长以外的都是普通的成员,每个进程组都有一个唯一的组ID,进程组的ID和组长的PID是一样的。

进程组中的成员是可以转移的,如果当前进程组中的成员被转移到了其他的组,或者进制中的所有进程都退出了,那么这个进程组也就不存在了。如果进程组中组长死了, 但是当前进程组中有其他进程,这个进程组还是继续存在的。下面介绍几个常用的进程组函数:

得到当前进程所在的进程组的组ID

pid_t getpgrp(void);

获取指定的进程所在的进程组的组ID,参数 pid 就是指定的进程

pid_t getpgid(pid_t pid);

将某个进程移动到其他进程组中或者创建新的进程组

int setpgid(pid_t pid, pid_t pgid);
  • 参数:
    • pid: 某个进程的进程ID
    • pgid: 某个进程组的组ID
      • 如果pgid对应的进程组存在,pid对应的进程会移动到这个组中, pid != pgid
      • 如果pgid对应的进程组不存在,会创建一个新的进程组, 因此要求 pid == pgid, 当前进程就是组长了
    • 返回值:函数调用成功返回0,失败返回-1

2. 会话

会话(session)是由一个或多个进程组组成的,一个会话可以对应一个控制终端, 也可以没有。一个普通的进程可以调用 setsid() 函数使自己成为新 session 的领头进程(会长),并且这个 session 领头进程还会被放入到一个新的进程组中。先来看一下 setsid() 函数的原型:

#include <unistd.h>

// 获取某个进程所属的会话ID
pid_t getsid(pid_t pid);

// 将某个进程变成会话 =>> 得到一个守护进程
// 使用哪个进程调用这个函数, 这个进程就会变成一个会话
pid_t setsid(void);

使用这个函数的注意事项:

1.调用这个函数的进程不能是组长进程, 如果是该函数调用失败,如果保证这个函数能调用成功呢? - 先fork()创建子进程, 终止父进程, 让子进程调用这个函数 2.如果调用这个函数的进程不是进程组长, 会话创建成功 - 这个进程会变成当前会话中的第一个进程,同时也会变成新的进程组的组长 - 该函数调用成功之后, 当前进程就脱离了控制终端,因此不会阻塞终端

Continue reading

「platformIO」printf 重映像、串口打印数据

2024-10-22 1 min read Docs Ronan

keil 环境中使用 printf 通过串口打印数据:

  • 在 main.c 引入stdio.h

  • 重写fputc函数

    // keil arm环境,如果你要用printf函数,就必须重写fputc函数,并且在魔术棒里面勾选使用Micro LIB
    int fputc(int ch, FILE *f)
    {
    	USART_SendData(USART1, ch);
    	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);//循环的判断串口是否发送完数据
    
    	return ch;
    }
    

    完成以上配置即可在 main 函数中使用 printf 函数通过串口打印数据。

arm-***-gcc 环境使用 printf 通过串口打印数据:

  • 不需要引入stdio.h头文件

  • 直接在 main.c 中重写_write方法即可

    // gcc 编译环境重写该方法
    //这是一种写法
    int _write( int fd, char *pBuffer, int size) {
        for (int i = 0; i < size; i++) {
            while ((USART1->SR&0x40) == 0);		// 等待串口发送完毕
            USART1->DR = (uint8_t) pBuffer[i];
        }
        return size;
    }
    
    //还有另一种写法,根据情况按需选择
    int _write( int fd, char *pBuffer, int size) {
        for (int i = 0; i < size; i++)
    	{
            while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);		// 等待串口发送完毕
            USART1->DR = (uint8_t) pBuffer[i];
        }
        return size;
    }
    
Older posts Newer posts