프로세스가 수동으로 실행되면 Linux ioctl VT_GETSTATE가 실패합니다.

프로세스가 수동으로 실행되면 Linux ioctl VT_GETSTATE가 실패합니다.

저는 ioctlC 프로그램에서 현재 tty를 얻기 위해 Linux에서 시스템 호출을 사용하고 있습니다.

ioctl프로그램을 수동으로(루트로) 실행하면 프로그램이 실패하는 이유를 알 수 없지만 init.d스크립트(루트로)를 사용하면 예상대로 작동합니다. GUI 세션에서 SSH 연결이나 터미널 애플리케이션을 사용하려고 합니다. 프로그램이 올바르게 실행되도록 하는 유일한 방법은 가상 터미널(CTRL+Fx, 여기서 x는 숫자)로 전환하고 거기에서 명령을 실행하는 것이었습니다. 이 프로그램을 RHEL8 및 RHEL6에서 테스트했습니다. RHEL8에서는 ("장치에 부적절한 ioctl") ioctl이 반환되고 ENOTTY, RHEL6에서는 오류가 EINVAL("잘못된 인수")입니다.

문제를 디버깅하기 위해 이 테스트 프로그램을 작성했지만 기본 프로그램과 다르게 동작하는 것 같습니다.

#include <stdlib.h> 
#include <stdio.h>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>

#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <linux/vt.h>
#include <linux/kd.h>

int main()
{

    long tty = -1;
    long fd = 0;
    int result = 0;
    struct vt_stat ttyinfo;

    fd = open("/dev/tty", O_RDWR | O_NOCTTY);

    if(fd <= 0) 
    {
        printf("Trying tty0\n");
        fd = open("/dev/tty0", O_RDWR | O_NOCTTY);

        if(fd <= 0)
        {
            printf("[open] error = %s\n" , strerror(errno) );
            return -1;
        }
    }

    result = ioctl(fd, VT_GETSTATE, &ttyinfo);

    if (result == 0) 
    {
        tty = ttyinfo.v_active;
        printf("tty: %d\n" , tty);
    }
    else
    {
        printf("[ioctl] error = %s\n" , strerror(errno) );
    }

    return 0;
}

참고: 이것은 단지 코드 조각일 뿐이며 실제 프로그램은 데몬이며 더 많은 작업을 수행합니다.

RHEL8:

UI 또는 SSH(실제 애플리케이션)에서 명령을 실행하고 /dev/tty 및 /dev/tty0을 시도하는 경우 보고되는 오류는 다음과 같습니다. Inproperty ioctl for device.

RHEL6: SSH /dev/tty를 사용하여 UI에서 명령(실제 애플리케이션)을 실행하는 경우 다음과 같은 오류가 보고됩니다. 잘못된 인수

왜 이런 일이 일어나는지 아십니까? 테스트 프로그램에 데몬을 추가해 보았는데, 테스트 프로그램은 계속 작동하는데 메인 프로그램은 작동하지 않습니다. 테스트 프로그램이 수행하지 않는 작업 중 메인 프로그램이 수행하는 다른 작업이 있어야 합니다.

답변1

가상 콘솔이 아닌 터미널에서 프로그램을 실행하고 있기 때문에 이런 일이 발생하는 것으로 의심됩니다./dev/tty제어 터미널에 대한 액세스를 제공하는 특수 장치입니다., 반드시 가상 콘솔은 아니지만 ioctl사용 중인 것은 가상 콘솔에만 적용됩니다.

fd포인트가 어딘가에 있는지 확인하면 프로그램이 안정적으로 실행됩니다.가상 콘솔, 루트로 실행할 때 이를 수행하는 가장 쉬운 방법은 /dev/tty0,활성 가상 콘솔입니다:

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/vt.h>

int main(int argc, char **argv) {
  long tty = -1;
  long fd = 0;
  int result = 0;
  struct vt_stat ttyinfo;

  fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
  if (fd < 0) {
    perror("Error opening /dev/tty0");
    return 1;
  }
  result = ioctl(fd, VT_GETSTATE, &ttyinfo);
  if (result == 0) {
    tty = ttyinfo.v_active;
    printf("Active tty: %ld\n", tty);
  } else {
    perror("ioctl failed");
  }
}

관련 정보