업데이트: 하단 참조
저는 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
, syslog+console
, console
, append:/var/log/accelMonitor.log
. 이러한 옵션 중 어느 것도 accelMonitor
콘솔, 로그 또는 .log 파일 에 인쇄되지 않는 것 같습니다 . 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