임베디드 CPU에서 실행중인 Linux 장치 드라이버를 개발 중입니다. 이 장치 드라이버는 일부 외부 하드웨어를 제어합니다. 외부 하드웨어에는 자체 DDR 컨트롤러 및 외부 DDR이 있습니다. 하드웨어의 DDR은 이동식 메모리 창을 통해 내장 CPU에서 볼 수 있습니다 (따라서 Linux 드라이버에서 외부 DDR에 대한 액세스를 페이징했습니다). Linux 커널 버전 2.6.33을 사용하고 있습니다.스레드가 버스 오류로 종료 될 때 세마포 잠금을 방지하려면 어떻게합니까?
내 드라이버는 sysfs를 사용하여 사용자 공간에서 외부 하드웨어를 제어 할 수 있도록합니다. 예를 들어 외부 하드웨어는 외부 DDR의 특정 주소를 증가시키는 하트 비트 카운터를 생성합니다. 드라이버는 외부 하드웨어가 여전히 실행 중인지 여부를 감지하기 위해이를 읽습니다.
외부 DDR이 올바르게 작동하지 않는 경우 외부 DDR에 액세스하면 내장 CPU에서 버스 오류가 발생합니다. 동시 다중 스레드 액세스를 방지하기 위해 드라이버는 세마포어를 사용합니다.
문제가 생겼습니다. 스레드가 세마포어를 잡고 버스 오류로 종료하면 세마포어는 여전히 잠겨 있습니다. 이후의 모든 호출은 무한대로 세마포 블록을 잡습니다. 운전 기사가 영원히 걸리지 않도록하기 위해 어떤 기술을 사용할 수 있습니까?
의 예 sysfs를 기능 (간체) 다음을 종료하는 대신 오류를 반환 할 수 있습니다 mwindow_get_reg()
있도록
static ssize_t running_attr_show(struct device *dev, struct device_attribute *attr, char *buffer)
{
struct my_device * const my_dev = container_of(dev, struct my_device, dev);
int ret;
if(down_interruptible(&my_dev->sem))
{
ret = -ERESTARTSYS;
}
else
{
u32 heartbeat;
int running;
// Following line could cause bus error
heartbeat = mwindow_get_reg(&my_dev->mwindow, HEARTBEAT_COUNTER_ADDR);
running = (heartbeat != my_dev->last_heartbeat) ? 1 : 0;
my_dev->last_heartbeat = heartbeat;
ret = sprintf(buffer, "%d\n", result);
/* unlock */
up(&my_dev->sem);
}
return ret;
}
감사 픽스 어셈블러는 그때 내 C 코드를 테스트 할 수있는 '폴트'플래그를 설정합니다. 확실히 고려해야 할 것. 예외 처리기가 버스 오류의 원인이 mwindow_get_reg의 호출임을 알 수있는 방법에 대한 제안이 있습니까? 우리는 접근 전에 정적 변수 세트에 의존하고 오류 동안 탐지되어 다른 정적 변수를 설정 한 다음 액세스 후에 검사하는 몇 가지 코드를 이미 가지고 있습니다. 인터럽트는 전체 프로세스 중에 비활성화됩니다. 이것은 매우 우아 해 보이지 않으며 많은 양의 펌웨어를 메모리 창을 통해 대상 DDR에 복사 할 때 장시간 동안 인터럽트가 비활성화되었다는 것을 의미합니다. – qbert220
@ qbert220 : 아키텍쳐의'copy_from_user()'구현을 살펴보십시오.이 함수는 반드시 복구 할 수없는 페이지 오류가 공포감을 유발하기보다는 호출자에게'EFAULT '를 반환하도록 설정해야합니다. 페이지 폴트 처리기가 작업의 일부분을 수행하는 방법). – caf
이것은 매우 간단한 아키텍처입니다. copy_to_user 구현은 access_ok (주소가 예상 범위에 있는지 확인)를 호출하고 false를 반환하면 -EFAULT를 반환합니다. 다른 모든 경우에는 memcpy를 호출하고 복사 요청 된 바이트 수를 반환합니다 (memcpy 반환 값은 무시됩니다). – qbert220