Forráskód Böngészése

修改优化代码

niujiuru 1 hónapja
szülő
commit
8ccfa624a0
4 módosított fájl, 185 hozzáadás és 6 törlés
  1. 2 2
      air720u/eth2net.go
  2. 171 0
      netmgrd/eth0net.go
  3. 0 0
      netmgrd/netmgrd.go
  4. 12 4
      readme.txt

+ 2 - 2
air720u/eth2net.go

@@ -20,7 +20,7 @@ import (
 	"hnyfkj.com.cn/rtu/linux/baseapp"
 )
 
-// 只保留需要使用的"eth2"网卡, 其它"eth*"网卡都被禁用掉(状态-离线)
+// 只保留需要使用的"eth2"网卡
 func disableEthBut2() error {
 	ifaces, err := net.Interfaces()
 	if err != nil {
@@ -43,7 +43,7 @@ func disableEthBut2() error {
 	return nil
 }
 
-// 分配上网地址, 成功后"udhcpc"会保持后台运行并占用"/dev/ttyUSB0"
+// 启动DHCP客户端, 请求IP地址
 func dialupEth2() error {
 	cmd1 := exec.Command("ip", "link", "set", "dev", "eth2", "up")
 	cmd1.Stdout = baseapp.Logger.WriterLevel(logrus.DebugLevel)

+ 171 - 0
netmgrd/eth0net.go

@@ -1 +1,172 @@
 package netmgrd
+
+import (
+	"fmt"
+	"net"
+	"os"
+	"os/exec"
+	"strconv"
+	"strings"
+	"syscall"
+	"time"
+
+	"github.com/sirupsen/logrus"
+	"hnyfkj.com.cn/rtu/linux/baseapp"
+)
+
+// 只保留需要使用的"eth0"网卡
+func disableEthBut0() error {
+	ifaces, err := net.Interfaces()
+	if err != nil {
+		return fmt.Errorf("获取网络接口列表失败: %w", err)
+	}
+
+	for _, iface := range ifaces {
+		if !strings.HasPrefix(iface.Name, "eth") || iface.Name == "eth0" {
+			continue
+		}
+
+		cmd := exec.Command("ip", "link", "set", "dev", iface.Name, "down")
+		cmd.Stdout = baseapp.Logger.WriterLevel(logrus.DebugLevel)
+		cmd.Stderr = baseapp.Logger.WriterLevel(logrus.ErrorLevel)
+		if err := cmd.Run(); err != nil {
+			return fmt.Errorf("关闭网口\"%s\"失败: %w", iface.Name, err)
+		}
+	}
+
+	return nil
+}
+
+// 启动DHCP客户端, 请求IP地址
+func dialupEth0() error {
+	cmd1 := exec.Command("ip", "link", "set", "dev", "eth0", "up")
+	cmd1.Stdout = baseapp.Logger.WriterLevel(logrus.DebugLevel)
+	cmd1.Stderr = baseapp.Logger.WriterLevel(logrus.ErrorLevel)
+	if err := cmd1.Run(); err != nil {
+		return fmt.Errorf("启动网口\"eth0\"失败: %w", err)
+	}
+
+	eth2pid := baseapp.RUN_DIR + "/udhcpc.eth0.pid"
+	cmd2 := exec.Command("udhcpc", "-b", "-i", "eth0", "-p", eth2pid)
+	cmd2.Stdout = baseapp.Logger.WriterLevel(logrus.DebugLevel)
+	cmd2.Stderr = baseapp.Logger.WriterLevel(logrus.ErrorLevel)
+	if err := cmd2.Run(); err != nil {
+		return fmt.Errorf("\"eth0\"请求地址失败: %w", err)
+	}
+
+	return nil
+}
+
+// 检测"eth0"网口上的"udhcpc"后台进程是否正在运行, 只保持一个实例
+func udhcpcEth0Exists() (bool, error) {
+	eth2pid := baseapp.RUN_DIR + "/udhcpc.eth0.pid"
+	data, err := os.ReadFile(eth2pid)
+	if err != nil {
+		return false, err
+	}
+	pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
+	if err != nil {
+		return false, err
+	}
+	err = syscall.Kill(pid, 0)
+	if err == nil { // 存在
+		return true, nil
+	}
+	if err == syscall.ESRCH { // 不存在
+		return false, nil
+	}
+	return false, err
+}
+
+// 杀死"eth0"网口上的"udhcpc"进程(根据上次运行时它的PID-文件记录)
+func KillEth0Udhcpc() error {
+	eth2pid := baseapp.RUN_DIR + "/udhcpc.eth0.pid"
+	data, err := os.ReadFile(eth2pid)
+	if err != nil {
+		return err
+	}
+	pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
+	if err != nil {
+		return err
+	}
+	if err := syscall.Kill(pid, syscall.SIGTERM); err != nil && err != syscall.ESRCH {
+		syscall.Kill(pid, syscall.SIGKILL)
+	}
+	return nil
+}
+
+// 强制杀死所有运行中的"udhcpc"进程,包括驻留在后台运行的(SIGKILL)
+func killAllUdhcpc() {
+	cmd := exec.Command("sh", "-c", `ps | grep '[u]dhcpc' | awk '{print $1}'`)
+	output, err := cmd.Output()
+	if err != nil {
+		return // 没找到也不是错误
+	}
+
+	pids := strings.FieldsSeq(string(output))
+	for pidStr := range pids {
+		pid, err := strconv.Atoi(pidStr)
+		if err != nil {
+			continue
+		}
+		if err := syscall.Kill(pid, syscall.SIGTERM); err != nil && err != syscall.ESRCH {
+			syscall.Kill(pid, syscall.SIGKILL)
+		}
+	}
+}
+
+// 运行"udhcpc"后, 获取"eth0"网口分配到的IPv4地址, 并校检其合法性
+func getEth0Addr() (ip, mask string, err error) {
+	iface, err := net.InterfaceByName("eth0")
+	if err != nil {
+		return "", "", fmt.Errorf("找不到网络接口\"eth0\": %w", err)
+	}
+
+	addrs, err := iface.Addrs()
+	if err != nil {
+		return "", "", fmt.Errorf("获取\"eth0\"的地址失败: %w", err)
+	}
+
+	for _, addr := range addrs {
+		ipNet, ok := addr.(*net.IPNet)
+		if !ok {
+			continue
+		}
+
+		ip4 := ipNet.IP.To4()
+		if ip4 == nil {
+			continue
+		}
+
+		if ip4.IsPrivate() { // 判断得到IP地址是否合法
+			return ip4.String(), net.IP(ipNet.Mask).String(), nil
+		} else {
+			return "", "", fmt.Errorf("分配给\"eth0\"的地址\"%s\"无效", ip4.String())
+		}
+	}
+
+	return "", "", fmt.Errorf("在\"eth0\"上未找到有效的IPv4 地址")
+}
+
+// 定时检测"eth0"网卡上的"udhcpc"后台服务进程, 发现退出时自动拉起
+func MonitorEth0Udhcpc(exitCh <-chan struct{}) {
+	t := time.NewTicker(time.Duration(5) * time.Second)
+	defer t.Stop()
+
+	for {
+		select {
+		case <-t.C:
+			bExists, _ := udhcpcEth0Exists()
+			if !bExists { // 清场一次
+				killAllUdhcpc()
+				disableEthBut0()
+			}
+			if !bExists && dialupEth0() == nil { // 重新进场
+				ip, mask, _ := getEth0Addr()
+				baseapp.Logger.Warnf("[%s] \"eth0\"重新分配的地址: %s/%s!", MODULE_NAME, ip, mask)
+			}
+		case <-exitCh:
+			return
+		} // select end
+	} // for end
+}

netmgrd/netmgr.go → netmgrd/netmgrd.go


+ 12 - 4
readme.txt

@@ -32,7 +32,15 @@ SHELL脚本封装库, 后台守护软件运行等功能, 可以平替硬件看
 海康机器人工业相机-G口, 通过海康提供的SDK, 封装实现拍照功能
 
 二、编译说明
-
-三、使用说明
-
-四、注意事项
+1, export交叉编译工具链"gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabihf"的位置到PATH环境变量
+2, make target=armv7hf
+3, make clean
+注释: 主要编译C语言时使用, Go语言不需要, 通过Makefile文件联合在一起编译
+
+三、附加说明
+1, 含C代码的模块一般都带有C编写的单元测试程序,可以在上位机上运行以下命令:
+   "valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes a.out"
+   进行内存泄露检查,通过检查后的模块代码才能放心使用
+
+2, 判断生成的armv7hf可执行文件依赖哪些依赖库,可以在上位机上运行以下命令:
+   arm-linux-gnueabihf-readelf -d ./a.out | grep NEEDED