커널 내부에 ioctl 구현

커널 내부에 ioctl 구현

저는 Linux 커널 4.19.2에서 작업하고 있습니다. perf나 그러한 도구를 사용하지 않고 사용 가능한 성능 카운터를 읽고 싶습니다.

사용자 공간에서는 아래와 같은 코드를 사용합니다.

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>

#define rdpmc(counter,low,high) \
     __asm__ __volatile__("rdpmc" \
        : "=a" (low), "=d" (high) \
        : "c" (counter))

void test(){
    printf(".");


}


static long
perf_event_open (struct perf_event_attr *hw_event, pid_t pid,
         int cpu, int group_fd, unsigned long flags)
{
  int ret;

  ret = syscall (__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
  return ret;
}





int
main ()
{
  unsigned long values1, values2;
  unsigned int fixed0, low, high;
  struct perf_event_attr pe;
  int fd, i;

  fixed0 = (1 << 30);

  memset (&pe, 0, sizeof (struct perf_event_attr));
  pe.type = PERF_TYPE_HARDWARE;
  pe.size = sizeof (struct perf_event_attr);
  pe.config = PERF_COUNT_HW_INSTRUCTIONS;
  pe.disabled = 1;
  pe.exclude_kernel = 0;
  pe.exclude_user = 0;
  pe.exclude_hv = 0;
  pe.exclude_idle = 0;

  fd = perf_event_open (&pe, 0, -1, -1, 0);
  if (fd == -1)
    {
      fprintf (stderr, "Error opening leader %llx\n", pe.config);
      exit (EXIT_FAILURE);
    }
for (i=1; i<=50; i++)
{
  ioctl (fd, PERF_EVENT_IOC_RESET, 0);
  ioctl (fd, PERF_EVENT_IOC_ENABLE, 0);

  rdpmc (fixed0, low, high);
  values1 = ((unsigned long) high << 32) + (unsigned long) low;

  test();

  rdpmc (fixed0, low, high);
  values2 = ((unsigned long) high << 32) + (unsigned long) low;

  ioctl (fd, PERF_EVENT_IOC_DISABLE, 0);
  printf (" %lu\n", values2 );  
}
  close (fd);
}

이제 커널 코드에서 동일한 것을 구현하고 싶습니다.

내 목표는 모든 컨텍스트 스위치에서 이벤트 수를 가져와 작업 구조에 저장하는 것입니다. 그래서 궁극적으로 커널의 context_switch() 함수에서 카운터를 호출하고 싶습니다. 커널에서 이 작업을 수행하면 항상 현재 스레드의 컨텍스트에서 실행된다는 이점이 있습니다.

대부분의 코드는 커널에서도 재사용될 수 있다고 생각합니다. 하지만 ioctl() 부분에 대해서는 잘 모르겠습니다.

답변1

기술적으로 ioctl은 커널 코드에서 호출될 수 있습니다. 그것은 알려져있다ksys_ioctl().[*] init/유일한 다른 코드가 ksys_ioctl()을 호출하는 방법에 주목하십시오. 가볍게 말하면 이것은 특이한 일입니다. 부르다성능커널 내부의 ioctl이 더 의심스러워 보입니다.

도착하다시작ksys_ioctl()이것이 왜 특이한지 이해하면서, 나는 이것이 여전히 논쟁의 여지가 있다는 점을 지적하고 싶습니다 fd. 파일 설명자의 번호입니다.현재 작업 범위 내에서(프로세스/스레드).

[편집] 내 목표는 모든 컨텍스트 스위치에서 이벤트 수를 가져와 작업 구조에 저장하는 것입니다. 그래서 궁극적으로 커널의 context_switch() 함수에서 카운터를 호출하고 싶습니다.

아아아.

그래서 네가 그랬어아니요커널에서 ioctl()을 호출하고 싶습니다. (ioctl()을 호출할 수 있는 파일 설명자가 없을 것입니다.아니요각 context_switch() 동안 현재 작업의 파일 테이블에 파일 설명자를 열기 시작하고 싶다고 생각합니다. 나중에 닫더라도).

perf이 시점에서 Linux 하위 시스템(부 버전) 을 구현하는 방법을 묻고 있습니다 . 하위 시스템에는 perf성능 카운터가 있습니다. 성능 카운터를 사용하려는 경우아니요하위 시스템의 경우 먼저 커널에서 지원을 perf비활성화해야 합니다 . perf프로세스 후반에 다음과 같은 관련 자료를 검토하는 데 시간을 투자해야 합니다.SDM(또는 관련 설명서 - 아직 확인하지 않았습니다).


ksys_*()[*] 참고 사항: 함수에 포인터를 전달할 때 제한이 있습니다. 기본적으로 그들은 __user당신이 사용하지 않는 한 커널 메모리가 아닌 메모리를 기대합니다.set_fs()..


코드 작성은 perf또 다른 이야기가 될 것입니다. 예를 들어 다음을 클릭하면 쉽게 코드를 찾아 볼 수 있습니다.PERF_EVENT_IOC_RESET. 특정 줄 외에도 살펴볼 소스 파일(및 디렉터리)도 제공되며 계속 클릭할 수 있습니다 :-). 그래서 나는 이것이 당신의 문제라고 생각하지 않습니다.

관련 정보