【瑞芯微Rockchip Linux平台】SoftAp需求实现(1)进程代码实现

本文详细阐述了在瑞芯微Linux平台上实现SoftAP热点的过程,包括启动命令封装、进程状态监控、dnsmasq和hostapd配置,以及异常处理和关键代码片段。

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

最近上层有个需求,需要实现启动SoftAp热点,如果记录下所有的实现过程。

本文链接:《【瑞芯微Rockchip Linux平台】SoftAp需求实现(1)进程代码实现

本系列文章链接:

  1. 【瑞芯微Rockchip Linux平台】SoftAp需求实现(1)进程代码实现
  2. 【瑞芯微Rockchip Linux平台】SoftAp需求实现(2)根据传参修改SSID和密码,SSID以wifi MAC地址后四位对结尾
  3. 【瑞芯微Rockchip Linux平台】SoftAp需求实现(3)动态获取BT Mac地址并更新beacon帧中的mac信息

一、SoftAp启动命令

其实这些,使用命令就能够实现,

  1. 打开命令如下:
    iw phy0 interface add wlan1 type managed
    ifconfig wlan1 up
    ifconfig wlan1 192.168.50.1 netmask 255.255.255.0
    route add default gw 192.168.50.1 wlan1
    dnsmasq -C /data/bin/dnsmasq_softap.conf --interface=wlan1
    hostapd /data/bin/hostapd.conf -t -B

  2. 关闭命令如下:
    kill -15 dnsmasq
    kill -15 hostapd
    route del -net 192.168.50.0 netmask 255.255.255.0 dev wlan1
    ifconfig wlan1 down
    iw dev wlan1 del

  3. 其他命令配置


二、SoftAp启动命令封装实现过程

根据上层的需求,将前面的这些命令进行封装,封装成库和都可执行程序都行。
本需求,我选择的是封装成可执行程序。

2.1 在log前添加系统时间

主要是利用宏控来重写printf函数,这样,在打印每一句log前都会调用get_cur_time获取下当前的系统时间,精确到ms。

#include <time.h>

static char *get_cur_time(void){
	static char s[50]={0};
	char s_ms[10]={0};
	time_t t;
	struct tm *ltime;
	struct timeval tv; 
	
	time(&t);
	ltime = localtime(&t);
	gettimeofday(&tv,NULL);  //tv.tv_sec * 1000 + tv.tv_usec / 1000;  
	
	strftime(s, 50, "%Y-%m-%d %H:%M:%S", ltime);
	sprintf(s_ms, ".%03d", tv.tv_usec / 1000);
	strcat(s, s_ms);
	
	return s;
}

#define printf_t(fmt, ...) printf("[%s][Dongle_Soft_ap] "fmt, get_cur_time(), ##__VA_ARGS__)

2.2 查看进程是否正在运行 process_is_alive()

这个比较简单,主要是通过ps -A | grep dnsmasq | wc -l 来对进程数量进行统计,如果数量大于等1,则说明当前进程正在运行。
该函数返回的是进程运行的数量。

int process_is_alive(const char *process)
{
	FILE *fp = NULL;
	int pid = 0;
	char buff_tmp[100]={0};

	sprintf(buff_tmp, "ps -A | grep %s | wc -l", process);
	fp = popen(buff_tmp, "r");
	if(fp){
		memset(buff_tmp, 0, 100);
		fgets(buff_tmp, sizeof(buff_tmp)-1, fp);
		pclose(fp);
		if(buff_tmp != NULL){
			pid = atoi(buff_tmp);
			return pid;
		}
	}	
	return -1;
}

2.3 杀死进程 kill_process()

通过 popen来获取命令的输出信息来解析到进程的进程号,然后再kill 掉。
一般来说,建议使用 kill -15 来杀进程,它会等待进程释放相关的资源,不容易出来资源泄漏的问题。

void kill_process(const char *process, int level)
{
	FILE *fp = NULL;
	int pid = 0;
	char buff_tmp[100]={0}, *p_buff=NULL, *p_buff1=NULL;

	sprintf(buff_tmp, "ps -A | grep %s", process);

	fp = popen(buff_tmp, "r");
	if(fp){
		memset(buff_tmp, 0, 100);
		while(fgets(buff_tmp, sizeof(buff_tmp)-1, fp) >0){
			p_buff = buff_tmp;
			while(p_buff!=NULL && *p_buff!='\0' && *p_buff==' ') p_buff++;
			p_buff1 = p_buff;
			while(p_buff1!=NULL && *p_buff1!='\0' && *p_buff1!=' ') p_buff1++;
			*p_buff1 = '\0';
			pid = atoi(p_buff);
			if( kill(pid, level) == 0)		// kill(pid, 15)
				printf_t("===>杀死后台%s进程(%d)(-%d) success\n",process,  pid, level);
		}
		pclose(fp);
	}
}

2.4 循环监控相关进程的运行状态

main函数中,主要工作 就是启动hostapdf进程,然后,循环监控hostapddnsmasq 进程的存活状态,
只要其中有任何一个进程出现异常,都会关注 softap热点,然后释放相关资源。

int main(int argc, char *argv[]){

	// 1. 启动前杀死现有的 dnsmasq 和 hostapd
	kill_all_process();
	usleep(200000);
	// 2. 启动 hostapd
	system("iw phy0 interface add wlan1 type managed");
	system("ifconfig wlan1 up");
	sleep(1);
	system("ifconfig wlan1 192.168.50.1 netmask 255.255.255.0");
	system("route add default gw  192.168.50.1 wlan1");
	printf_t("===>运行命令:dnsmasq -C /data/bin/dnsmasq_softap.conf  --interface=wlan1\n");
	system("dnsmasq -C /data/bin/dnsmasq_softap.conf  --interface=wlan1");
	printf_t("===>运行命令:hostapd /data/bin/hostapd.conf -t -B\n");
	system("hostapd /data/bin/hostapd.conf -t -B");
		
	printf_t("===>开始循环监控dnsmasq 和 hostapd -------\n");
	while(keep_alive == 1){
		sleep(1);
		
		if( process_is_alive("dnsmasq") == 0){
			printf_t("===>dnsmasq进程异常,开始关闭hostap\n");
			break;
		}
		if( process_is_alive("hostapd") == 0){
			printf_t("===>hostapd进程异常,开始关闭hostap\n");
			break;
		}
	}

	// 3. 恢复初始状态
	kill_all_process();
	printf_t("===>route del -net 192.168.50.0 netmask 255.255.255.0 dev wlan1\n");
	system("route del -net 192.168.50.0 netmask 255.255.255.0 dev wlan1");
	printf_t("===>ifconfig wlan1 down\n");
	system("ifconfig wlan1 down");
	system("iw dev wlan1 del");
	
	printf_t("程序运行结束-------------\n");

	return 0;
}

2.5 添加异常处理函数

添加一个全局变量keep_alive 用于确认当前进程是否需要主动退出。

main函数中,注册SIGINT、SIGABRT、SIGTERM、SIGKILL四个信号,绑定函数sig_handler
当过程在运行过程中,收到这四个信号中的任何一个,都会进入sig_handler函数,将keep_alive清0,结束main函数中的循环监控,释放相关的资源。

void sig_handler( int sig )
{
    if ( sig == SIGINT ||  sig == SIGABRT ||  sig == SIGTERM ||  sig == SIGKILL)
    {
        keep_alive = 0;
		printf_t("===>收到停止信号, keep_alive=%d\n", keep_alive);
    }
}

int main(int argc, char *argv[]){
	// 注册异常处理函数
	signal( SIGINT, sig_handler );
	signal( SIGABRT, sig_handler );
	signal( SIGTERM, sig_handler );
	signal( SIGKILL, sig_handler );
}

三、dnsmasq.conf 文件配置

user=root
# listen-address=127.0.0.1

except-interface=usb0

#interface=p2p-wlan0-0
# dhcp-option=p2p-wlan0-0,1,255.255.225.0     #指定掩码
# dhcp-option=p2p-wlan0-0,3,192.168.50.1     #指定网关
# dhcp-option=p2p-wlan0-0,6,192.168.50.1     #指定dns
dhcp-range=192.168.50.2,192.168.50.51

# log-queries
# log-facility=/data/dnsmasq.log

四、hostapd.conf 文件配置

interface=wlan0
ctrl_interface=/var/run/hostapd
driver=nl80211
ssid=soft-ap

auth_algs=1
wpa=2
wpa_passphrase=12345678
wpa_key_mgmt=WPA-PSK
#wpa_pairwise=TKIP
rsn_pairwise=CCMP

# 5G 149 
channel=149
hw_mode=a
ieee80211ac=1
ignore_broadcast_ssid=0

# 2.4G  6
#channel=6
#hw_mode=g
#ieee80211n=1
#ignore_broadcast_ssid=0

五、完整代码

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

static int keep_alive = 1;

static char *get_cur_time(void){
	static char s[50]={0};
	char s_ms[10]={0};
	time_t t;
	struct tm *ltime;
	struct timeval tv; 
	
	time(&t);
	ltime = localtime(&t);
	gettimeofday(&tv,NULL);  //tv.tv_sec * 1000 + tv.tv_usec / 1000;  
	
	strftime(s, 50, "%Y-%m-%d %H:%M:%S", ltime);
	sprintf(s_ms, ".%03d", tv.tv_usec / 1000);
	strcat(s, s_ms);
	
	return s;
}
#define printf_t(fmt, ...) printf("[%s][Dongle_Soft_ap] "fmt, get_cur_time(), ##__VA_ARGS__)

void sig_handler( int sig )
{
    if ( sig == SIGINT ||  sig == SIGABRT ||  sig == SIGTERM ||  sig == SIGKILL)
    {
        keep_alive = 0;
		printf_t("===>收到停止信号, keep_alive=%d\n", keep_alive);
    }
}

int process_is_alive(const char *process)
{
	FILE *fp = NULL;
	int pid = 0;
	char buff_tmp[100]={0};

	sprintf(buff_tmp, "ps -A | grep %s | wc -l", process);
	fp = popen(buff_tmp, "r");
	if(fp){
		memset(buff_tmp, 0, 100);
		fgets(buff_tmp, sizeof(buff_tmp)-1, fp);
		pclose(fp);
		if(buff_tmp != NULL){
			pid = atoi(buff_tmp);
			return pid;
		}
	}	
	return -1;
}

void kill_process(const char *process, int level)
{
	FILE *fp = NULL;
	int pid = 0;
	char buff_tmp[100]={0}, *p_buff=NULL, *p_buff1=NULL;

	sprintf(buff_tmp, "ps -A | grep %s", process);

	fp = popen(buff_tmp, "r");
	if(fp){
		memset(buff_tmp, 0, 100);
		while(fgets(buff_tmp, sizeof(buff_tmp)-1, fp) >0){
			p_buff = buff_tmp;
			while(p_buff!=NULL && *p_buff!='\0' && *p_buff==' ') p_buff++;
			p_buff1 = p_buff;
			while(p_buff1!=NULL && *p_buff1!='\0' && *p_buff1!=' ') p_buff1++;
			*p_buff1 = '\0';
			pid = atoi(p_buff);
			if( kill(pid, level) == 0)		// kill(pid, 15)
				printf_t("===>杀死后台%s进程(%d)(-%d) success\n",process,  pid, level);
		}
		pclose(fp);
	}
}

void kill_all_process(void)
{
	if( process_is_alive("dnsmasq") >= 1){
		kill_process("dnsmasq", 15);     // kill -15
		usleep(10000);		//10ms 后重新检测是否关注成功
		if( process_is_alive("dnsmasq") >= 1){
			kill_process("dnsmasq", 9); // 暴力关闭 kill -9
		}
	}
	if( process_is_alive("hostapd") >= 1){
		kill_process("hostapd", 15);     // kill -15
		sleep(1);		//1ms 后重新检测是否关注成功
		if( process_is_alive("hostapd") >= 1){
			kill_process("hostapd", 9); // 暴力关闭 kill -9
		}
	}
}


int main(int argc, char *argv[]){
	// 注册异常处理函数
	signal( SIGINT, sig_handler );
	signal( SIGABRT, sig_handler );
	signal( SIGTERM, sig_handler );
	signal( SIGKILL, sig_handler );

	// 1. 启动前杀死现有的 dnsmasq 和 hostapd
	kill_all_process();
	usleep(200000);
	// 2. 启动 hostapd
	system("iw phy0 interface add wlan1 type managed");
	system("ifconfig wlan1 up");
	sleep(1);
	system("ifconfig wlan1 192.168.50.1 netmask 255.255.255.0");
	system("route add default gw  192.168.50.1 wlan1");
	printf_t("===>运行命令:dnsmasq -C /data/bin/dnsmasq_softap.conf  --interface=wlan1\n");
	system("dnsmasq -C /data/bin/dnsmasq_softap.conf  --interface=wlan1");
	printf_t("===>运行命令:hostapd /data/bin/hostapd.conf -t -B\n");
	system("hostapd /data/bin/hostapd.conf -t -B");
		
	printf_t("===>开始循环监控dnsmasq 和 hostapd -------\n");
	while(keep_alive == 1){
		sleep(1);
		
		if( process_is_alive("dnsmasq") == 0){
			printf_t("===>dnsmasq进程异常,开始关闭hostap\n");
			break;
		}
		if( process_is_alive("hostapd") == 0){
			printf_t("===>hostapd进程异常,开始关闭hostap\n");
			break;
		}
	}

	// 3. 恢复初始状态
	kill_all_process();
	printf_t("===>route del -net 192.168.50.0 netmask 255.255.255.0 dev wlan1\n");
	system("route del -net 192.168.50.0 netmask 255.255.255.0 dev wlan1");
	printf_t("===>ifconfig wlan1 down\n");
	system("ifconfig wlan1 down");
	system("iw dev wlan1 del");
	
	printf_t("程序运行结束-------------\n");

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小馋喵星人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值