[Linux/C] Probleem met eigen device driver

Pagina: 1
Acties:

  • eppie
  • Registratie: Maart 2000
  • Niet online
(overleden)
Hallo,

Ik ben bezig met het maken van een character driver voor het aansturen van leds op de printerpoort onder linux. Nou dacht ik dat het probleem in mijn code zat maar na het downloaden van een enorm simpele module had ik nog steeds het zelfde probleem.

Eerst de code:
code:
1
2
3
4
5
6
7
8
9
ssize_t my_read(struct file *filep,char *buff,size_t count,loff_t *offp )
{
        char my_data[10] = "yo";
    /* function to copy kernel space buffer to user space*/
    if ( copy_to_user(buff,my_data,strlen(my_data)) != 0 )
        printk( "Kernel -> userspace copy failed!\n" );
    return strlen(my_data);

}


Deze code is van het simpele voorbeeld.

Als ik deze module laad en een cat uitvoer op de devfile dan krijg ik niet 1 keer "yo" zoals ik verwacht, maar een oneindig aantal keer "yo". en dit wil ik natuurlijk niet. Wat doe ik hier dan fout?
Kan het met search en google niet echt vinden :(

Weet ook niet zeker of dit topic in programming of dit forum.

Alvast bedankt!

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Waarschijnlijk is my_read niet blocking, oftewel hij blijft gaan zelfs als er geen data is om te lezen.

Overigens kun je beter dit doen:
C:
1
2
3
4
5
6
7
8
9
10
11
12
ssize_t my_read(struct file *filep, char *buff, size_t count, loff_t *offp)
{
    char my_data[10];
    memset(my_data,0x0,10);
    strncpy("yo",my_data,2);

    /* function to copy kernel space buffer to user space*/
    if ( copy_to_user(buff,my_data,strlen(my_data)) != 0 )
        printk( "Kernel -> userspace copy failed!\n" );
    
    return strlen(my_data);
}

Strings in c moet je altijd 0 terminaten.
FF uit het blote hoofd dus waarschijnlijk werkt het niet ;)

Btw ik neem aan dat je de Module HOWTO al had gevonden? Of The Linux Kernel Module Programming Guide

[ Voor 20% gewijzigd door MTWZZ op 21-06-2006 14:25 ]

Nu met Land Rover Series 3 en Defender 90


  • eppie
  • Registratie: Maart 2000
  • Niet online
(overleden)
thx zal het is proberen!

Ik maak gebruik van het boek Linux device drivers 3e druk. :)

Had die 2e link al gezien maar ook daar doen ze in de read code niets bijzonders :)
http://www.tldp.org/LDP/lkmpg/2.6/html/x569.html

En als ik hem gewoon open via een open() call in een apart test proggie dan werkt het wel goed :S

[ Voor 63% gewijzigd door eppie op 21-06-2006 15:14 ]


  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Mja testproggies en de kernel zijn toch net ff anders :P

Nu met Land Rover Series 3 en Defender 90


  • eppie
  • Registratie: Maart 2000
  • Niet online
(overleden)
Bedoel dan wel dat ik de device filevan me kernelmodule open via een testproggie ipv met cat ;)

Verwijderd

eppie schreef op woensdag 21 juni 2006 @ 13:16:
code:
1
2
3
4
5
6
7
8
9
ssize_t my_read(struct file *filep,char *buff,size_t count,loff_t *offp )
{
        char my_data[10] = "yo";
    /* function to copy kernel space buffer to user space*/
    if ( copy_to_user(buff,my_data,strlen(my_data)) != 0 )
        printk( "Kernel -> userspace copy failed!\n" );
    return strlen(my_data);

}


Als ik deze module laad en een cat uitvoer op de devfile dan krijg ik niet 1 keer "yo" zoals ik verwacht, maar een oneindig aantal keer "yo". en dit wil ik natuurlijk niet. Wat doe ik hier dan fout?
Cat werkt grofweg als volgt:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int res, wres, total, rfd = open ("/dev/iets", O_RDONLY), wfd = fileno (stdout);
char buf[1024];
do {
  if ((res = read (rfd, buf, sizeof (buf)) > 0) {
    do {
      total = 0;
      wres = write (wfd, &buf[total], res - total);
      if (wres > 0)
        total += wres;
    } while (wres > 0 && total < res);
    if (wres < 0) {
      perror ("write");
      break;
    }
  } else {
    if (res < 0)
      perror ("read");
    break;
  }
} while (res > 0);


Nu, je leest dus iets uit in een loop en roept je bovenstaande code eenmaal aan. Dan krijg je "yo". Vervolgens doet 'ie dat opnieuw, en krijg je dus een loop... De output onderscheidt verder niks, dus je zult een oneindig aantal "yo"s krijgen. Hier wat tips:
• hou je state bij, gebruik bv. een dprintk() om het aantal keren dat my_read() is aangeroepen bij te houden. Je kan dan bv. na de eerste "yo" 0 returnen, zodat 'ie snapt dat het end-of-file is.
• als dit niet voor school is, zorg dat je een goed logisch denkend vermogen hebt en dat je ontzettend goed in C bent (d.w.z., dat je code-flow snapt). Dit is niet noodzakelijk, maar wel enorm handig als je wilt gaan kernel-proggen. Ik heb het idee dat je nog niet echt geweldig gewend bent aan C ( :? ).

edit:
write-/read-fd uit elkaar gehaald.

[ Voor 14% gewijzigd door Verwijderd op 22-06-2006 14:28 ]


  • blaataaps
  • Registratie: Juli 2001
  • Niet online
Deze kan ook in Programming, tikje die kant op dus :)

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 19-02 19:53

Creepy

Tactical Espionage Splatterer

Overigens kan je vanuit userspace ook prima direct de printerpoort aansturen. Heb je een speciale reden waarom je dat vanuit een device driver wilt doen?

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Ivo
  • Registratie: Juni 2001
  • Laatst online: 14-01-2025

Ivo

code:
1
2
3
4
5
6
7
8
9
10
11
ssize_t my_read(struct file *filep,char *buff,size_t count,loff_t *offp )
{
        /* Detect EOF */
        if (!*offp) return 0;
        char my_data[10] = "yo";
    /* function to copy kernel space buffer to user space*/
    if ( copy_to_user(buff,my_data,strlen(my_data)) != 0 )
        printk( "Kernel -> userspace copy failed!\n" );
    return strlen(my_data);

}

Met Beelzebubu's uitleg kom je dan tot dit.
Pagina: 1