改用现代C++封装SocketCAN,嵌入式CAN通信更安全
在嵌入式Linux上做CAN通信,SocketCAN几乎是标准选择。内核提供的接口很直接,但用C去操作就有些琐碎:手动创建socket、绑定接口、收发帧,每一步都得自己处理错误和资源释放。稍不留神,不是socket泄露就是数据越界。
现代C++的RAII和类型系统刚好能解决这些问题。下面是一个简单的封装,把socket的生命周期交给对象管理。
用RAII管好socket生命周期
CanSocket的构造函数做了三件事:创建原始socket、获取接口索引、完成绑定。如果中间哪一步失败,析构函数会自动清理已经分配的资源,不用在错误路径里手动close。
class CanSocket {
public:
explicit CanSocket(const std::string& interface) {
sockfd_ = ::socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (sockfd_ < 0) {
throw CanException("Socket creation failed");
}
struct ifreq ifr;
std::strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ);
if (ioctl(sockfd_, SIOCGIFINDEX, &ifr) < 0) {
close(sockfd_);
throw CanException("Interface index retrieval failed");
}
struct sockaddr_can addr;
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(sockfd_, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
close(sockfd_);
throw CanException("Socket bind failed");
}
}
~() {
(sockfd_ >= ) {
(sockfd_);
}
}
( CanSocket&) = ;
CanSocket& =( CanSocket&) = ;
(CanSocket&& other) : (other.sockfd_) {
other.sockfd_ = ;
}
:
sockfd_ = ;
};

