更新:下の参照
私はsystemdバージョン241を使用してdebian Linuxでsystemdサービスを作成しました。その目的は、accelMonitor.c
カーネルモジュールに接続されているコンパイルされたバージョンを起動することです。このカーネルモジュールは、加速度計のGPIO割り込みに応答するスクリプト用のイベントを提供します。イベントを受信したら、accelMonitor
デバイスの向きをコンソールに印刷します。スクリプトをサービスに変換するシステム単位ファイルはaccelMonitor
次のとおりです。
[Unit]
Description=Accelerometer Orientation Monitor
[Service]
Type=simple
ExecStartPre=/etc/systemd/system/deviceFileCreator
ExecStart=/etc/systemd/system/accelMonitor
RemainAfterExit=true
KillMode=process
StandardOutput=append:/var/log/accelMonitor.log
StandardError=append:/var/log/accelMonitor.log
[Install]
WantedBy=multi-user.target
サービスは最初にコンパイルされたスクリプトを実行して、deviceFileCreator.c
カーネルモジュール用のデバイスファイルを生成してaccelMonitor
通信します。その後、サービスはaccelMonitor
そのデバイスファイルを介してカーネルモジュールに登録されたスクリプト自体を実行します。現在、出力がファイルに書き込まれていますaccelMonitor.log
。deviceFileCreator
どちらのスクリプトもステートメントをaccelMonitor
使用し、printf
Cで書かれています。
私の質問はこの質問に対する答えです。: スクリプトが実行されると、deviceFileCreator
printf ステートメントがaccelMonitor.log
ファイルに正しく書き込まれます。ただし、accelMonitor
スクリプトが実行されると、両方のスクリプトがcにあり、printfを使用しても印刷ステートメントが.logファイルに正しく書き込まれません。 systemdサービスに精通している人なら、以下のコードを見て、なぜこれが起こるのかを簡単に理解できることを願っています。明確にすると、accelMonitor
サービスとして実行されていない場合はコンソールに正しく印刷されます。
私が今まで試したこと:
サービス単位ファイル自体で、次のオプションを試しましたStandardOutput
:syslog
、、、、。これらのオプションのどれもコンソール、ログ、または.logファイルに印刷されないようです。加速度計割り込みが発生した後にリセットされるため、スクリプトが実行されていると確信しています。syslog+console
console
append:/var/log/accelMonitor.log
accelMonitor
accelMonitor
accelMonitor
また、問題が発生した場合に備えて、デバイスファイルを生成する部分をdeviceFileCreator
以前に実行されたスクリプトに分割しました。何も変更されていないようですが、この変更が有効になったら、accelMonitor.service
start()で実行中であると印刷します[ OK ] Started Accelerometer Orientation Monitor
。以前はそうではありませんでしたが、まだ実行は終了します。
Type=oneshot
それ以外は試してみましたType=simple
。
誰かが私がなぜログ情報を取得できないのかについての洞察を与えることができればaccelMonitor
幸いdeviceFileCreator
です。ありがとうございます!
ファイルdeviceFileCreator.c
は次のとおりです。
// deviceFileCreator.c
#include <stdio.h>
#include <limits.h>
#include <signal.h>
#include <fcntl.h>
// Helper function to run bash commands in c
// This allows me to create the device file using terminal commands
char* exec(char* cmd) {
FILE* fp;
int status;
char path[PATH_MAX];
char* regValue;
fp = popen(cmd, "r");
if (fp == NULL)
/* Report error */
perror("popen error");
while (fgets(path, PATH_MAX, fp) != NULL)
//printf("%s", path);
regValue = path;
status = pclose(fp);
if (status == -1) {
/* Error reported by pclose() */
printf("Error reported by pclose()");
}
return regValue;
}
int main() {
int fd;
printf("Creating Device File irq_signal \n");
// Command to create device file
exec("sudo mknod /dev/irq_signal c 64 0");
/* Open the device file */
fd = open("/dev/irq_signal", O_RDONLY);
if (fd < 0) {
perror("Could not open device file\n");
return -1;
}
printf("Device file /dev/irq_signal created \n");
return 0;
}
起動時にこのスクリプトが実行されると、accelMonitor.logの出力は次のようになります。
Creating Device File irq_signal
Device file /dev/irq_signal created
ファイルaccelMonitor.c
は次のとおりです。
/*
Event handler to monitor signals from
associated kernel module. Triggers whenever
an interrupt is detected by the kernel module
(gpio_irq) from the MMA8451Q accelerometer and
is passed as a signal (SIGTX 44) to this script.
This occurs everytime the device orientation changes
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <string.h>
#include <sys/time.h>
#include <limits.h>
#include <error.h>
#include <stdbool.h>
/* Signals to connect to Kernel Module */
#define SIGTX 44
#define REGISTER_UAPP _IO('R', 'g')
/* Define registers to be accessed on Accelerometer over i2c */
const char* deviceADDR = " 0x1C";
const char* PL_STATUS = " 0x10";
const char* INT_SOURCE = " 0x0C";
const char* PL_CFG = " 0x11";
const char* PL_COUNT = " 0x12";
const char* CTRL_REG1 = " 0x2A";
const char* CTRL_REG3 = " 0x2C";
const char* CTRL_REG4 = " 0x2D";
const char* CTRL_REG5 = " 0x2E";
/* Defines function structure for i2c-tools package */
const char* cmdGet = "i2cget -y 2";
const char* cmdSet = "i2cset -y 2";
/* Enum for current device orientation state */
enum position { left, right, down, up };
enum position oriented;
/* Function that runs bash commands in c
Allowing one to use the i2c-tools package */
char* exec(char* cmd) {
FILE* fp;
int status;
char path[PATH_MAX];
char* regValue;
fp = popen(cmd, "r");
if (fp == NULL)
/* Report error */
perror("popen error");
while (fgets(path, PATH_MAX, fp) != NULL)
//printf("%s", path);
regValue = path;
status = pclose(fp);
if (status == -1) {
/* Error reported by pclose() */
printf("Error reported by pclose()");
}
return regValue;
}
/* Function that performs i2cget */
char* get(const char* reg1, const char* reg2) {
char str[100];
char str2;
strcpy(str, cmdGet);
strcat(str, reg1);
strcat(str, reg2);
char* regValue = exec(str);
return regValue;
}
/* Function that performs i2cset */
char* set(const char* reg1, const char* reg2, const char* value) {
char str[100];
char str2;
strcpy(str, cmdSet);
strcat(str, reg1);
strcat(str, reg2);
strcat(str, value);
//printf("%s\n",str);
char* regValue = exec(str);
return regValue;
}
/* Helper function to check whether or not a bit k is set */
bool bitSet(char* x, int k) {
int n = strtoul(x, NULL, 16);
//printf("%d\n", n);
if (n & (1 << (k - 1))) {
return true;
}
else {
return false;
}
}
/* Event handler for signal from Kernel Module */
void signalhandler(int sig) {
// Never Prints
printf("Event Detected");
// This clears the interrupt, which is how I know the script is functioning
char* orientation = get(deviceADDR, PL_STATUS);
if (bitSet(orientation, 2) && bitSet(orientation, 3) && oriented != left) {
printf("Landscape Left \n");
oriented = left;
}
else if (!bitSet(orientation, 2) && bitSet(orientation, 3) && oriented != right) {
printf("Landscape Right \n");
oriented = right;
}
else if (bitSet(orientation, 2) && !bitSet(orientation, 3) && oriented != down) {
printf("Portrait Down \n");
oriented = down;
}
else if (!bitSet(orientation, 2) && !bitSet(orientation, 3) && oriented != up) {
printf("Portrait Up \n");
oriented = up;
}
}
int main() {
int fd;
signal(SIGTX, signalhandler);
/* Configure the Accelerometer */
printf("Configuring Accelerometer...\n");
set(deviceADDR, CTRL_REG1, " 0x00"); // Put in Standby
set(deviceADDR, CTRL_REG1, " 0x20"); // Set data rate to 50Hz
set(deviceADDR, PL_CFG, " 0x40"); // Enable orientation detection
set(deviceADDR, CTRL_REG4, " 0x10"); // Enable interrupts
set(deviceADDR, CTRL_REG5, " 0x10"); // Route interrupt to INT1 pin
set(deviceADDR, PL_COUNT, " 0x05"); // Set debounce to 100ms
set(deviceADDR, CTRL_REG1, " 0x02"); // Set interrupt to Active High
set(deviceADDR, CTRL_REG1, " 0x01"); // Put in Active Mode
get(deviceADDR, PL_STATUS); // Read PL_STATUS to clear initial interrupt
printf("Configured!\n");
// Also does not print
printf("PID: %d\n", getpid());
/* Open the device file */
fd = open("/dev/irq_signal", O_RDONLY);
if (fd < 0) {
perror("Could not open device file\n");
return -1;
}
/* Register app to Kernel Module */
if (ioctl(fd, REGISTER_UAPP, NULL)) {
perror("Error registering app");
close(fd);
return -1;
}
/* Wait for Signal */
printf("Wait for signal...\n");
while (1)
sleep(1);
return 0;
}
出力は以下から来ます。systemctl status accelMonitor.service
● accelMonitor.service - Accelerometer Orientation Monitor
Loaded: loaded (/lib/systemd/system/accelMonitor.service; enabled; vendor pre
Active: active (running) since Thu 2022-11-17 17:06:52 UTC; 26min ago
Process: 565 ExecStartPre=/etc/systemd/system/deviceFileCreator (code=exited,
Main PID: 655 (accelMonitor)
Tasks: 1 (limit: 1026)
Memory: 1.3M
CGroup: /system.slice/accelMonitor.service
└─655 /etc/systemd/system/accelMonitor
Nov 17 17:06:49 beaglebone systemd[1]: Starting Accelerometer Orientation Monitor..
Nov 17 17:06:52 beaglebone sudo[573]: root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/bin/mknod /dev/irq_signal c 64 0
Nov 17 17:06:52 beaglebone sudo[573]: pam_unix(sudo:session): session opened for user root by (uid=0)
Nov 17 17:06:52 beaglebone sudo[573]: pam_unix(sudo:session): session closed for user root
Nov 17 17:06:52 beaglebone deviceFileCreator[565]: Creating Device File irq_signal
Nov 17 17:06:52 beaglebone deviceFileCreator[565]: Device file /dev/irq_signal created
Nov 17 17:06:52 beaglebone systemd[1]: Started Accelerometer Orientation Monitor.
修正する
使用する代わりに明示的およびバージョンprintf("Hello")
に切り替えました。これは機能しますが、どちらもサービス単位ファイル(現在)で同じ設定に設定されていますが、stderrストリームのみを印刷するという新しい問題があります。fprintf(stdout,"Hello")
fprintf(stderr,"Hello")
StandardOutput
StandardError
syslog