[英]Using a userspace driver in Linux daemon
I'm trying to write a daemon that monitors the state of a USB GPIO device (Velleman VM167) and will then act on changed.我正在尝试编写一个守护程序来监视 USB GPIO 设备 (Velleman VM167) 的状态,然后将根据更改采取行动。
I've found a userspace driver ( https://github.com/rahlskog/VM167 ) and have set some /etc/udev rules and ldconfig paths so that I can run the test and it works as expected.我找到了一个用户空间驱动程序 ( https://github.com/rahlskog/VM167 ) 并设置了一些 /etc/udev 规则和 ldconfig 路径,以便我可以运行测试并按预期工作。
If I compile the following it works as expected:如果我编译以下内容,它会按预期工作:
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sys/stat.h>
#include <syslog.h>
#include <unistd.h>
#include <vector>
#include "VM167.h"
int test_openDevices();
void test_readWriteDigital(int card);
void test_readAnalog(int card);
void test_PWM(int card);
int main(void)
{
syslog(LOG_INFO, "Loop");
int devices;
devices = OpenDevices();
if (devices == 0)
{
syslog(LOG_ERR, "Driver error condition, exiting");
//fflush(stdout);
//return -1;
}
else if (devices == -1)
{
syslog(LOG_ERR, "No devices found on system, exiting\n");
//fflush(stdout);
//return -1;
}
int ver = VersionDLL();
syslog(LOG_INFO, "DLL Version: %d.%d.%d.%d\n", (ver>>24), (ver>>16)&0xFF, (ver>>8)&0xFF, ver&0xFF);
}
Syslog:系统日志:
Nov 4 01:12:12 testserver console: Loop
Nov 4 01:12:12 testserver console: DLL Version: 0.1.0.19
However when I add this to a daemon template I can no longer see the USB card...但是,当我将它添加到守护程序模板时,我再也看不到 USB 卡了...
#include <dirent.h>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <sys/stat.h>
#include <syslog.h>
#include <unistd.h>
#include <vector>
#include "VM167.h"
int test_openDevices();
void test_readWriteDigital(int card);
void test_readAnalog(int card);
void test_PWM(int card);
void do_heartbeat()
{
// TODO: implement processing code to be performed on each heartbeat
syslog(LOG_INFO, "Loop");
int devices;
devices = OpenDevices();
if (devices == 0)
{
syslog(LOG_ERR, "Driver error condition, exiting");
//fflush(stdout);
//return -1;
}
else if (devices == -1)
{
syslog(LOG_ERR, "No devices found on system, exiting\n");
//fflush(stdout);
//return -1;
}
int ver = VersionDLL();
syslog(LOG_INFO, "DLL Version: %d.%d.%d.%d\n", (ver>>24), (ver>>16)&0xFF, (ver>>8)&0xFF, ver&0xFF);
}
// For security purposes, we don't allow any arguments to be passed into the daemon
int main(void)
{
// Define variables
pid_t pid, sid;
// Fork the current process
pid = fork();
// The parent process continues with a process ID greater than 0
if(pid > 0)
{
exit(EXIT_SUCCESS);
}
// A process ID lower than 0 indicates a failure in either process
else if(pid < 0)
{
exit(EXIT_FAILURE);
}
// The parent process has now terminated, and the forked child process will continue
// (the pid of the child process was 0)
// Since the child process is a daemon, the umask needs to be set so files and logs can be written
umask(0);
// Open system logs for the child process
openlog("Daemon-GPIO", LOG_NOWAIT | LOG_PID, LOG_USER);
syslog(LOG_NOTICE, "Successfully started Daemon-GPIO");
// Generate a session ID for the child process
sid = setsid();
// Ensure a valid SID for the child process
if(sid < 0)
{
// Log failure and exit
syslog(LOG_ERR, "Could not generate session ID for child process");
// If a new session ID could not be generated, we must terminate the child process
// or it will be orphaned
exit(EXIT_FAILURE);
}
// Change the current working directory to a directory guaranteed to exist
if((chdir("/")) < 0)
{
// Log failure and exit
syslog(LOG_ERR, "Could not change working directory to /");
// If our guaranteed directory does not exist, terminate the child process to ensure
// the daemon has not been hijacked
exit(EXIT_FAILURE);
}
// A daemon cannot use the terminal, so close standard file descriptors for security reasons
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// Daemon-specific intialization should go here
const int SLEEP_INTERVAL = 5;
// Enter daemon loop
while(1)
{
syslog(LOG_INFO, "Starting helper loop");
// Execute daemon heartbeat, where your recurring activity occurs
do_heartbeat();
// Sleep for a period of time
sleep(SLEEP_INTERVAL);
}
// Close system logs for the child process
syslog(LOG_NOTICE, "Stopping Daemon-GPIO");
closelog();
// Terminate the child process when the daemon completes
exit(EXIT_SUCCESS);
}
Syslog:系统日志:
Nov 4 00:18:10 testserver Daemon-GPIO[29638]: Loop
Nov 4 00:18:10 testserver Daemon-GPIO[29638]: No devices found on system, exiting
Nov 4 00:18:10 testserver Daemon-GPIO[29638]: DLL Version: 0.1.0.19
Whelp, seems I forgot to close the device each loop.小鬼,似乎我忘记在每个循环中关闭设备。 That's resolved it.
这样就解决了。
CloseDevices();
You call OpenDevices()
at the start of every loop.您在每个循环开始时调用
OpenDevices()
。 Surely, you need to close them at the end of the loop.当然,您需要在循环结束时关闭它们。 Since your real (commented out) code has early returns, the proper C++ way of dealing with this is to add a RAII wrapper around
OpenDevices()
and CloseDevices()
to make sure that opened devices are also closed.由于您的真实(注释掉)代码会提前返回,因此处理此问题的正确 C++ 方法是在
OpenDevices()
和CloseDevices()
周围添加一个 RAII 包装器,以确保打开的设备也已关闭。
Example:例子:
// A wrapper that open devices on creation and closes them on destruction,
// like when it goes out of scope.
struct DeviceCtx {
DeviceCtx() : devices(OpenDevices()) {}
~DeviceCtx() { CloseDevices(); }
operator int() const { return devices; } // implicit conversion to `int`
int devices;
};
void do_heartbeat() { //
syslog(LOG_INFO, "Loop");
DeviceCtx devices; // calls OpenDevices
if (devices == 0) {
syslog(LOG_ERR, "Driver error condition, exiting");
return; // CloseDevices() will be called
} else if (devices == -1) {
syslog(LOG_ERR, "No devices found on system, exiting\n");
return; // CloseDevices() will be called
}
int ver = VersionDLL();
syslog(LOG_INFO, "DLL Version: %d.%d.%d.%d\n", (ver >> 24),
(ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
} // `devices` goes out of scope and calls CloseDevices()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.