Linux 장치 드라이버 개발 세부 정보 2

11 장 메모리 및 I / O 액세스

각 프로세스의 사용자 공간은 완전히 독립적이고 서로 독립적이며 각 사용자 프로세스에는 다른 페이지 테이블이 있습니다. 커널 공간은 kernel
의해 매핑 되며 프로세스와 함께 변경되지 않으며 수정되었습니다. 커널 공간의 가상 주소 대 물리적 주소 매핑은 모든 프로세스가 공유합니다 커널
의 가상 공간은 다른 프로그램과 독립적입니다
11.3 메모리 액세스
11.3.1
사용자 공간 메모리의 동적 적용 메모리의 동적 적용 기능 사용자 공간에는 malloc ()이 있으며, 다양한 운영 체제에서이 함수의 사용은 일관
되고 malloc ()에서 요청한 메모리의 해제 기능은 free ()입니다. Linux의 경우 C 라이브러리의 malloc () 함수는 일반적으로
두 개의 시스템 호출 인 brk () 및 mmap ()을 통해 커널의 메모리에 적용됩니다.
사용자 공간 C 라이브러리의 malloc 알고리즘에는 실제로 2 차 관리 기능이 있기 때문에 모든 애플리케이션 및 메모리 릴리스가 반드시
커널에 대한 시스템 호출을 동반하는 것은 아닙니다 . 예를 들어, Listing 11.2의 애플리케이션은 커널에서 메모리를 가져온 직후
free ()를 호출 할 수 있습니다 .free ()는 이전에 mallopt (M_TRIM_THRESHOLD, -1) 및
mallopt (M_MMAP_MAX, 0)를 호출 하기 때문에이 free ()는 그렇지 않습니다. 메모리는 커널로 반환되지만 C 라이브러리의 할당 알고리즘으로 만 반환됩니다 (
메모리는 여전히이 프로세스에 속함). 따라서 모든 후속 동적 메모리 응용 프로그램 및 릴리스는 사용자 모드에서 수행됩니다.
코드 목록 11.2 사용자 공간 메모리 애플리케이션과 mallopt

#include <malloc.h>
#include <sys/mman.h>
#define SOMESIZE (100*1024*1024) // 100MB

int main(int argc, char *argv[])
{
 unsigned char *buffer;
 int i;

 if (mlockall(MCL_CURRENT | MCL_FUTURE))
 mallopt(M_TRIM_THRESHOLD, -1);
 mallopt(M_MMAP_MAX, 0);

 buffer = malloc(SOMESIZE);
 if (!buffer)
 exit(-1);

 /*
 * Touch each page in this piece of memory to get it
 * mapped into RAM
 */
 for (i = 0; i < SOMESIZE; i += page_size)
 buffer[i] = 0;
 free(buffer);
 /* <do your RT-thing> */

 return 0;
}


또한 Linux 커널은 항상 요구 페이징을 사용하므로 malloc ()이 반환되면 성공적으로
반환 하더라도 커널은 실제로 프로세스 메모리를 제공하지 않습니다. 이때 요청 된 메모리를 읽으면 내용 All은 0, 이 페이지의
매핑은 읽기 전용입니다. 특정 페이지가 작성 될 때만 커널은 실제로 페이지 폴트 후 프로세스에이 페이지를 제공합니다.

11.4 장치 I / O 포트 및 I / O 메모리 액세스
장치는 일반적으로 장치를 제어하고, 장치를 읽고 쓰고, 장치 상태 (즉, 제어 레지스터, 데이터 레지스터 및 데이터 레지스터)를 얻기위한 레지스터 세트를 제공합니다. 상태
레지스터. 이러한 레지스터는 I / O 공간에 위치하거나 메모리 공간에 위치 할 수 있습니다. I / O 공간에있을 때는 일반적으로 I / O
포트 라고 하고 메모리 공간에있을 때는 해당 메모리 공간을 I / O 메모리라고합니다.

11.4.1 Linux I / O 포트 및 I / O 메모리 액세스 인터페이스
1. I / O 포트
Linux 장치 드라이버에서 Linux 커널에서 제공하는 기능을 사용하여 I / O 공간에있는 포트에 액세스해야합니다. 다음
종류.
1) 바이트 포트 읽기 및 쓰기 (8 비트 폭).
unsigned inb (unsigned port);
void outb (unsigned char byte, unsigned port);
2) 워드 포트 읽기 및 쓰기 (16 비트 폭).
unsigned inw (unsigned port);
void outw (unsigned short word, unsigned port);
3) long word port (32 비트 폭)를 읽고 씁니다.
unsigned inl (unsigned port);
void outl (unsigned longword, unsigned port);
4) 바이트 문자열을 읽고 씁니다.
void insb (unsigned port, void * addr, unsigned long count);
void outsb (unsigned port, void * addr, unsigned long count);
5) insb () port port에서 count 바이트를 읽고 read 결과는 addr가 가리키는 메모리; outsb ()
addr 가 가리키는 메모리의 count 바이트를 port로 시작하는 포트에 계속 기록합니다.
6) 일련의 단어를 읽고 씁니다.
void insw (unsigned port, void * addr, unsigned long count);
void outsw (unsigned port, void * addr, unsigned long count);
7) 긴 단어 문자열을 읽고 씁니다.
void insl (unsigned port, void * addr, unsigned long count);
void outsl (unsigned port, void * addr, unsigned long count);
위 함수의 I / O 포트 번호 포트 유형은 특정 하드웨어 플랫폼에 따라 크게 다릅니다. , 따라서 여기에는 unsigned 만 기록됩니다.
2.
I / O 메모리 커널의 I / O 메모리 (일반적으로 칩의 I2C, SPI, USB 및 기타 컨트롤러의 레지스터 또는 외부 메모리 버스의 장치)에 액세스하기 전에 ioremap ()을 사용해야합니다. 장치를 설정하는 기능 물리적 주소가 가상 주소에 매핑됩니다. ioremap ()의
프로토 타입은 다음과 같습니다 :
void * ioremap (unsigned long offset, unsigned long size);
ioremap ()은 vmalloc ()과 유사하며 새 페이지 테이블도 생성해야하지만 수행하지 않습니다. vmalloc ()
할당 동작 에서 실행되는 메모리 . ioremap ()은 특정 물리적 주소 범위에 액세스하는 데 사용할 수있는 특수 가상 주소를 반환합니다.이 가상
주소는 vmalloc 매핑 영역에 있습니다. ioremap ()에서 얻은 가상 주소는 iounmap () 함수로 해제해야하며 프로토 타입은 다음과 같습니다.
void iounmap (void * addr);
 

11.4.4 장치 주소를 사용자 공간에
매핑 1. 메모리 매핑 및 VMA
사용자 공간은 불가능하며 장치에 직접 액세스해서는 안되지만 mmap ()
함수 는 장치 드라이버에서 구현 하여 사용자 공간을 만들 수 있습니다. 직접 액세스 장치의 물리적 주소입니다. 사용자 공간의 메모리 세그먼트를 장치 메모리와 연결합니다. 사용자가 사용자 공간에서이 주소 범위에 액세스 
하면 실제로 장치에 대한 액세스로 변환됩니다.
이 기능은 디스플레이 어댑터와 같은 장치에 매우 의미가 있습니다. 사용자 공간이 메모리 맵을 통해 비디오 메모리에 직접 액세스 할 수 있다면
화면 프레임의 각 픽셀은 사용자 공간에서 커널 공간으로 복사하는 프로세스가 더 이상 필요하지 않습니다.
mmap ()은 PAGE_SIZE 단위로 매핑되어야합니다. 실제로 메모리는 페이지 단위로만 매핑 될 수 있습니다.
PAGE_SIZE 정수 배수가 아닌 주소 범위 를 매핑 하려면 먼저 페이지 정렬을 수행하고 PAGE_SIZE의 배수로 매핑됩니다.
file_operations 파일 작업 구조에서 드라이버의 mmap () 함수의 프로토 타입은 다음과 같은 것을 알 수 있습니다.
int (* mmap) (struct file *, struct vm_area_struct *);
드라이버의 mmap () 함수는 사용자 시스템에서 mmap () 수행 최종적으로 호출되면 호출됩니다 .mmap () 시스템 호출
의 프로토 타입은 아래와 같이 file_operations의 mmap () 프로토 타입과 매우 다릅니다.
caddr_t mmap (caddr_t addr, size_t len, int prot, int 플래그, int fd, off_t 오프셋);

사용자가 mmap ()을 호출하면 커널은 다음 처리를 수행합니다.
1) 프로세스의 가상 공간에서 VMA 조각을 찾습니다. 2)이 VMA를 매핑합니다.
3) 장치 드라이버 또는 파일 시스템의 file_operations가 mmap () 작업을 정의하면이를 호출합니다.
4)이 VMA를 프로세스의 VMA 연결 목록에 삽입합니다.
file_operations에서 mmap () 함수의 첫 번째 매개 변수는 1) 단계에서 찾은 VMA입니다.
mmap () 시스템 호출에 의해 매핑 된 메모리는 munmap ()에 의해 매핑 해제 될 수 있습니다.이 함수의 프로토 타입은 다음과 같습니다.
int munmap (caddr_t addr, size_t len);

대부분의 장치 드라이버는 장치 메모리를 사용자 공간에 매핑하는 기능을 제공 할 필요가 없습니다. 직렬 포트와 같은 스트림 지향
장치의 경우 이러한 종류의 매핑을 구현하는 것은 의미가 없기 때문입니다 . 디스플레이, 비디오 및 기타 장치의 경우 매핑을 설정하면 사용자 공간과 커널 공간 간의
메모리 복사 를 줄일 수 있습니다.

 

11.5 I / O 메모리 정적 매핑

주변 I / O 메모리 물리적 주소에서 가상 주소로의 정적 매핑을 설정합니다. map_desc
map_desc structure
struct map_desc {  unsigned long virtual; / * virtual address * /  unsigned long pfn; / * __phys_to_pfn (phy_addr) * /  unsigned long length; / * 크기 * /  unsigned int 유형; / * 유형 * / };




static struct map_desc ixdp2x01_io_desc _ _initdata = {  .virtual = IXDP2X01_VIRT_CPLD_BASE,  .pfn = _ _phys_to_pfn (IXDP2X01_PHYS_CPLD_BASE),  .length  = IXDP2X01_CPLD_REGION_SIZE }; 정적 무효 _ _init ixdp2x01_map_io (void) {  ixp2000_map_io ();  iotable_init (& ixdp2x01_io_desc, 1); // 建立 页 映射}











11.6 DMA

DMA는 CPU의 개입없이 주변 장치와 시스템 메모리간에 양방향 데이터 전송을 허용하는 하드웨어 메커니즘입니다. DMA
를 사용하면 시스템 CPU가 실제 I / O 데이터 전송 프로세스를 제거하여 시스템 처리량을 크게 향상시킬 수 있습니다.

DMA 모드에서의 데이터 전송은 DMA 컨트롤러 (DMAC)에 의해 제어되며 전송 중에 CPU는 동시에 다른 작업을 수행 할 수 있습니다.
DMA가 종료되면 DMAC는 데이터 전송이 인터럽트를 통해 종료되었음을 CPU에 알리고 CPU는
사후 처리를 위해 해당 인터럽트 서비스 루틴을 실행합니다 .
 

12 장 Linux 장치 드라이버의 소프트웨어 아키텍처 생각
 

추천

출처blog.csdn.net/csdn1126274345/article/details/102539664