Forum: PC-Programmierung Absturz bei "insmod"


von Markus R. (mark989)


Lesenswert?

Hi,

bei meinem Netzwerk/SPI-Modul lässt sich das Modul mitfolgender 
Initialisierung leider nicht per insmod einbinden, das System(Raspbian) 
reagiert auf nichts mehr. Wenn ich allerdings tx_ring in probe als 
lokale Variable deklariere funktioniert alles einwand frei. Hat jemand 
eine Idee wo hier eine Unsauberkeit oder ein Fehler liegt?
1
struct tps1_net {
2
        struct net_device   *netdev;
3
        struct spi_device   *spi;
4
  struct sk_skbuff   *tx_skb;
5
  struct sk_buff_head   *tx_ring;
6
  u32 msg_enable;
7
  u8 spi_transfer_buf[1200];
8
};
9
struct tps1_net *tps;
10
...
11
static int __devinit tps1_probe(struct spi_device *spi)
12
{
13
  ...
14
  skb_queue_head_init(tps->tx_ring);
15
  return 0;
16
  ...
17
}

von Thomas H. (thomash2)


Lesenswert?

So sollte man das sowieso nicht machen, vermeide globale Pointer.

struct tps1_net *tps;

hast du tps denn irgendwo allokiert? Besser du definierst diese nur fuer 
die jeweilige Instanz und nicht global. Wenn der Treiber nun aus 
irgendeinem Grund die Probe Funktion ein 2. Mal aufruft wuerdest du die 
Werte erneut ueberschreiben.
Ohne die gesamte Datei gesehen zu haben aber auch etwas schwierig.

von Markus R. (mark989)


Angehängte Dateien:

Lesenswert?

Also:
Ich habe jetzt in der probe Funktion es per priv = netdev_priv(dev); 
realisiert. Trotzdem lässt sich das Modul nicht laden??
Mit einer lokalen Variable (struct sk_buff_head *tx_ring;) in probe 
jedoch schon?!


Mein erster Ansatz mit globale Pointer lag daran, dass ich Funktionen 
einer API aufrufe die am Ende meine TPS1_SendReceiveData-Funktion 
aufrufen(für die SPI-Komm), da in dieser Funktion aber tps->spi 
benpötigt wird, hieße es dass ich den dev-Parameter quer durch die ganze 
API mitschleppen muss. Da der Treiber jedoch sowieso nur einmal geladen 
wird, habe ich mir den Aufwand die API umzuschreiben gespart.

Danke für jede Hilfe

von Karl H. (kbuchegg)


Lesenswert?

Auf welches tps1_net Objekt zeigt denn dein Zeiger tps?

Ich kann in deinem Code weder eine Allokierung eines entsprechenden 
Objektes finden, noch sonst irgendetwas, wie der Zeiger je auf ein 
derartiges Objekt zeigen könnte.

Nur weil du eine entsprechende Pointer Variable hast, hast du deswegen 
noch lange kein derartiges Objekt!


Genauso die ganzen Pointer in
1
struct tps1_net {
2
        struct net_device   *netdev;
3
        struct spi_device   *spi;
4
  struct sk_skbuff   *tx_skb;
5
  struct sk_buff_head   *tx_ring;
6
  u32 msg_enable;
7
  u8 spi_transfer_buf[1200];
8
};

die zeigen nicht magisch irgendwo hin, sondern du musst sie auf 
entsprechende Objekte zeigen lassen, in dem du den Pointern mal irgendwo 
gültige Adresse von existierenden Objekten zuweist.


> Mein erster Ansatz ...
Mit Verlaub. Aber dein erster Ansatz sollte sein, erst mal C von der 
Pieke auf zu lernen.

von Markus R. (mark989)


Lesenswert?

>Mit Verlaub. Aber dein erster Ansatz sollte sein, erst mal C von der
>Pieke auf zu lernen.
Könnte besser sein, da hast du recht.
Die Pointer netdev und spi werden in probe mit Objekten verheiratet und 
tx_ring wird mit skb_queue_head_init() initialisiert, dabei habe ich mal 
angenommen das hier die allocation vorgenommen wird. Oder??
1
struct net_device   *netdev;
2
struct spi_device   *spi;
3
struct sk_skbuff   *tx_skb;
4
struct sk_buff_head   *tx_ring;
5
6
priv->netdev   = dev;  
7
priv->spi   = spi;     
8
skb_queue_head_init(priv->tx_ring);

von Markus R. (mark989)


Lesenswert?

Das Problem liegt in der probe-Funktion da sich das modul nicht einmal 
laden lässt. Um genau zu sein an skb_queue_head_init(priv->tx_ring); . 
Ohne geht es. Oder sehe ich das falsch?

von Karl H. (kbuchegg)


Lesenswert?

Markus R. schrieb:
>>Mit Verlaub. Aber dein erster Ansatz sollte sein, erst mal C von der
>>Pieke auf zu lernen.
> Könnte besser sein, da hast du recht.
> Die Pointer netdev und spi werden in probe mit Objekten verheiratet und
> tx_ring wird mit skb_queue_head_init() initialisiert, dabei habe ich mal
> angenommen das hier die allocation vorgenommen wird. Oder??

Ich hab jetzt nicht alles analysiert.
Ich hab nach Verwendungen des Zeigers tps, dem hier
1
struct tps1_net *tps;
gesucht, weil der es ist, der in der ersten Funktion verwendet wird.
1
USIGN32 TPS1_SendReceiveData(u8* transmit, unsigned short length, u8* receive)
2
{
3
4
  struct spi_message msg;
5
  int ret = 0;
6
  int i;
7
8
  for(i = 0; i < length; i++){
9
10
    struct spi_transfer t = {
11
                .tx_buf = transmit +i,
12
                .rx_buf = receive  +i,
13
                .len = 1,
14
        };
15
16
           spi_message_init(&msg);
17
           spi_message_add_tail(&t, &msg);
18
19
           ret = spi_sync(tps->spi, &msg);
20
                          ***
21
                          ***
bzw. sinngemäss dann auch in anderen Funktionen.

Und ich habe keine Zuweisung dafür gefunden. Damit zeigt dieser Pointer 
'in den Wald' (ist NULL), es sei denn ich hab übersehen, wo dieser 
POinter entsprechend bearbeitet wird um auf ein Objekt zu zeigen.

von Karl H. (kbuchegg)


Lesenswert?

Markus R. schrieb:
>>Mit Verlaub. Aber dein erster Ansatz sollte sein, erst mal C von der
>>Pieke auf zu lernen.
> Könnte besser sein, da hast du recht.
> Die Pointer netdev und spi werden in probe mit Objekten verheiratet und
> tx_ring wird mit skb_queue_head_init() initialisiert, dabei habe ich mal
> angenommen das hier die allocation vorgenommen wird. Oder??
>
>
1
> struct net_device   *netdev;
2
> struct spi_device   *spi;
3
> struct sk_skbuff   *tx_skb;
4
> struct sk_buff_head   *tx_ring;
5
> 
6
> priv->netdev   = dev;
7
> priv->spi   = spi;
8
> skb_queue_head_init(priv->tx_ring);
9
>

und was hat das alles mit dem Pointer tps zu tun?

Der ist es, der zb hier
1
static int __devinit tps1_probe(struct spi_device *spi)
2
{
3
  ...
4
  skb_queue_head_init(tps->tx_ring);
5
  return 0;
6
  ...
7
}
verwendet wird!
Wo zeigt der Pointer hin? Auf welches Objekt? Wo ist das zugehörige 
struct tps1_net Objekt, auf das er zeigt?

von Markus R. (mark989)


Lesenswert?

Also, ich habe zuerst in probe Funktion auch alles mit dem globalen 
Pointer tps implementiert:
1
tps->netdev   = dev;
2
tps->spi   = spi;
So hat alles funktionert. Dann habe ich mit
1
skb_queue_head_init(tps->tx_ring);
die queue initialisiert, was auch kompiliert wird. Jedoch lässt es sich 
nicht als Modul einbinden. Warum? Der Grund warum ich es mit einem 
globalen Pointer mache ist, ich müsste den dev oder priv pointer durch 
die ganze API bis zur TPS1_SendReceiveData-Methode durchschleppen, -> 
großer Aufwand, die API ist nicht gerade klein. Und weil dieses Modul 
sowieso nur einmal eingebunden wird , kann ich auch globale Pointer 
benutzten. Oder hat dies noch weitere Nachteile?

von Georg A. (georga)


Lesenswert?

tps hat als Pointer aber immer noch keinen gültigen Wert. Mach doch vor 
dem ersten tps->netdev=... doch mal ein tps=kmalloc(...).

von Karl H. (kbuchegg)


Lesenswert?

Markus R. schrieb:
> Also, ich habe zuerst in probe Funktion auch alles mit dem globalen
> Pointer tps implementiert:
>
1
> tps->netdev   = dev;
2
> tps->spi   = spi;
3
>
> So hat alles funktionert.


Sagen wir so: Es ist nicht gleich abgestürzt.
Funktionieren im Sinne von 'so ist es richtig' ist was anderes.

> Dann habe ich mit
>
1
> skb_queue_head_init(tps->tx_ring);
2
>
> die queue initialisiert, was auch kompiliert wird. Jedoch lässt es sich
> nicht als Modul einbinden. Warum? Der Grund warum ich es mit einem
> globalen Pointer mache ist, ich müsste den dev oder priv pointer durch
> die ganze API bis zur TPS1_SendReceiveData-Methode durchschleppen, ->
> großer Aufwand, die API ist nicht gerade klein. Und weil dieses Modul
> sowieso nur einmal eingebunden wird , kann ich auch globale Pointer
> benutzten. Oder hat dies noch weitere Nachteile?

Dann frage ich mich, wozu du überhaupt Pointer benutzt.
Man nimmt keine Pointer wenn man nicht muss.

Wozu soll das hier
1
int j;
2
int* pj;
3
4
void foo()
5
{
6
  *pj = 5;
7
}
8
9
int main()
10
{
11
  pj = &j;
12
  foo();
13
}

gut sein, wenn ein simples
1
int j;
2
3
void foo()
4
{
5
  j = 5;
6
}
7
8
int main()
9
{
10
  foo();
11
}
genau dasselbe macht? Wozu über einen Pointer auf ein tatsächliches 
Objekt verweisen, wenn es nicht sein muss und da du auf globalen 
Variablen bestehst, auch nichts bringt?
1
int j;
2
3
void foo( int* tmp )
4
{
5
  *tmp = 5;
6
}
7
8
int main()
9
{
10
  foo( &j );
11
}
das wäre insofern besser, als dann die Funktion mit allen möglichen 
int-Variablen aufgerufen werden kann und nicht an die globale Variable 
gebunden ist.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

Und beachte. Das hier ....

>
1
> 
2
> int j;
3
> int* pj;
4
> 
5
> void foo()
6
> {
7
>   *pj = 5;
8
> }
9
> 
10
> int main()
11
> {
12
>   pj = &j;
13
>   foo();
14
> }
15
>

... funktioniert deshalb, weil es eine int-Variable gibt (j), und dafür 
gesorgt wird, dass der Pointer auf ein int Objekt zeigt ( pj = &j; ).

UNd genau das vermisse ich in deinem Code. Dein Pointer zeigt nicht auf 
ein Objekt. Ob man dieses Objekt jetzt bekommt, weil man es sowieso 
anlegt
1
...
2
3
struct tps1_net tps_object;
4
struct tps1_net *tps = &tps1_object;
5
....

oder weil man es dynamisch allokiert
1
...
2
struct tps1_net *tps;
3
4
int main()
5
{
6
  tps = malloc( sizeof(struct tps1_net) );
7
8
  ....
9
10
11
  free( tps );
12
}

ist erst mal egal. Wichtig ist, dass der Pointer auf ein Objekt zeigen 
muss! Das tut er nicht automatisch. Nur weil du einen Pointer hast, hast 
du nicht automatisch auch das dahinterliegende Objekt.
Ein POinter ist nichts anderes als ein Kartekärtchen in einer 
Bibliothek, auf dem steht, wo das echte Buch zu finden ist. Aber nur 
weil du das Karteikärtchen in der Hand hast, hast du noch lange nicht 
das Buch. Und umgekehrt: nur weil du ein Karteikärtchen anlegst, taucht 
nicht magisch das zugehörige BUch in den Regalen auf. Erst mal musst du 
das Buch haben, dann kannst du ein Karteikärtchen anlegen, auf dem 
vermerkt ist, in welchem Regal das Buch zu finden ist.
Was dann in dem Buch steht und ob du da Notizen reinscheibst, ist wieder 
eine andere Sache. Aber um das tun zu können, brauchst du das Buch! Und 
nicht einfach nur ein Karteikärtchen auf dem auf ein fiktives Buch 
verwiesen wird.

von Markus R. (mark989)


Lesenswert?

Mir ist klar was Zeiger sind. In anderen Netzwerktreibern wie dem 
enc28j60(
http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/enc28j60.c) 
wird dies zwar ohne globale Pointer gemacht, aber der Zeiger *priv 
bekommt auch nirgendswo eine Speicher-Allokierung. Mit
1
tps = netdev_priv(dev);
wird lediglich ein Zeiger tps zugewiesen, der bereits hier
1
dev = alloc_etherdev(sizeof(struct tps1_net));
allokiert wurde!!
Es wird, wie ich es aus dem enc28j60-Treiber verstehe immer durch *dev 
auf die "Hauptstruktur" zugegriffen(in meinem Fall tps). Dh. tps zeigt 
auf die Adresse: "netdev_priv(dev)".

Nun zu meinem eigentlichen Problem: Mit
1
skb_queue_head_init(tps->tx_ring);
stürtzt das System bei insmod ab, ohne nicht. (tx_ring-alloc erledigt)
Jemand eine Idee?

von lange weg (Gast)


Lesenswert?

hi,

ich bin schon lange weg von linux treiber entwicklung aber mir kommt da 
so manches komisch vor:
1
printk("probe called!\n");
2
  struct net_device *dev;
3
  struct tps1_net *priv;
4
  int ret = 0;
5
6
  dev = alloc_etherdev(sizeof(struct tps1_net));

dev ist vom type net_device allozierst aber tps1_net größe, sind die 
gleich groß, ist das die gleich struktur?

1
  if(!dev){
2
3
    if (netif_msg_drv(&debug))
4
                        dev_err(&spi->dev, DRV_NAME ": unable to alloc new ethernet\n");
5
    ret = -ENOMEM;
6
                goto error_alloc;
7
  }  
8
  
9
  priv = netdev_priv(dev);
10
11
  priv->netdev = dev;     /* tps to netdev reference */
12
  priv->spi = spi;        /* tps to spi reference */
13
14
  dev->netdev_ops = &tps1_netdev_ops;  
15
  random_ether_addr(dev->dev_addr);
16
  //SET_ETHTOOL_OPS(dev, &tps1_ethtool_ops);

zuerst weißt du mithilfe von dev priv zu und dann verwendest du in der 
priv struct dev... und dev registrierst du dann. so aus dem bauch ist 
das etwas komisch, aber ist schon mehr als 5 jahre her ...

von Andreas B. (andreas_b77)


Lesenswert?

Markus R. schrieb:
> Nun zu meinem eigentlichen Problem:
> Mitskb_queue_head_init(tps->tx_ring);
> stürtzt das System bei insmod ab, ohne nicht. (tx_ring-alloc erledigt)
> Jemand eine Idee?

Ja. tps->tx_ring ist nicht initialisiert, zeigt also nicht auf ein 
struct sk_buff_head. Zumindest sehe ich hier nirgends eine Allokation.

von Karl H. (kbuchegg)


Lesenswert?

Markus R. schrieb:

> bekommt auch nirgendswo eine Speicher-Allokierung. Mit
>
1
> tps = netdev_priv(dev);
2
>
> wird lediglich ein Zeiger tps zugewiesen, der bereits hier
>
1
> dev = alloc_etherdev(sizeof(struct tps1_net));
2
>
> allokiert wurde!!

wo genau passiert das in dem von dir geposteten Code?
Also der erste Teil
1
  tps = netdev_priv(dev);

> auf die "Hauptstruktur" zugegriffen(in meinem Fall tps). Dh. tps zeigt
> auf die Adresse: "netdev_priv(dev)".

Auch das ist für mich mit dem geposteten Code nicht nachvollziehbar


> Nun zu meinem eigentlichen Problem: Mit

Das IST dein eigentliches Problem!
Der Pointer tps ist nicht gültig! Der zeigt auf kein Objekt sondern ist 
höchst wahrscheinlich ein NULL-Pointer.

Wie oft denn noch?

von Karl H. (kbuchegg)


Lesenswert?

Nach einem kurzen Überfliegen ein paar Dokus im Netz denke ich, dass das 
hier
>
1
> static int __devinit tps1_probe(struct spi_device *spi)
2
> {
3
>   printk("probe called!\n");
4
>   struct net_device *dev;
5
>   struct tps1_net *priv;
6
>   int ret = 0;
7
>
8
>   dev = alloc_etherdev(sizeof(struct tps1_net));
9
>   if(!dev){
10
11
>     if (netif_msg_drv(&debug))
12
>       dev_err(&spi->dev, DRV_NAME ": unable to alloc new ethernet\n");
13
>     ret = -ENOMEM;
14
>       goto error_alloc;
15
>  }  
16
>  
17
>  priv = netdev_priv(dev);
18
> 
19
>   priv->netdev = dev;     /* tps to netdev reference */
20
>   priv->spi = spi;        /* tps to spi reference */
21
22
...

eigentlich so lauten sollte
1
static int __devinit tps1_probe(struct spi_device *spi)
2
{
3
  printk("probe called!\n");
4
  struct net_device *dev;
5
  int ret = 0;
6
7
  dev = alloc_etherdev(sizeof(struct tps1_net));
8
  if(!dev){
9
10
    if (netif_msg_drv(&debug))
11
                        dev_err(&spi->dev, DRV_NAME ": unable to alloc new ethernet\n");
12
    ret = -ENOMEM;
13
                goto error_alloc;
14
  }  
15
  
16
  tps = netdev_priv(dev);
17
18
  tps->netdev = dev;     /* tps to netdev reference */
19
  tps->spi = spi;        /* tps to spi reference */
20
...

dann hast du auch deinen globalen tps Pointer eingerichtet.

Und dann natürlich auch
1
  skb_queue_head_init( tps->tx_ring );
wobei ich jetzt nauch rauskriegen muss, ob das überhaupt so stimmt. Denn 
wieder. Der tx_ring member zeigt ja im Moment noch auf gar nichts. WIe 
soll skb denn da jetzt eine Queue darauf einrichten?

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:


> Und dann natürlich auch
>
1
>   skb_queue_head_init( tps->tx_ring );
2
>
> wobei ich jetzt nauch rauskriegen muss, ob das überhaupt so stimmt. Denn
> wieder. Der tx_ring member zeigt ja im Moment noch auf gar nichts. WIe
> soll skb denn da jetzt eine Queue darauf einrichten?

Je mehr ich lese, desto überzeugter bin ich, dass das eigentlich so
1
struct tps1_net {
2
  struct net_device   *netdev;
3
  struct spi_device   *spi;
4
  struct sk_skbuff    *tx_skb;
5
  struct sk_buff_head  tx_ring;
6
  u32 msg_enable;
7
  u8 spi_transfer_buf[1200];
8
};
9
10
11
.....
12
13
  skb_queue_head_init( &(tps->tx_ring) );

aussehen sollte.

von Markus R. (mark989)


Lesenswert?

lange weg schrieb:
>  dev = alloc_etherdev(sizeof(struct tps1_net));
>dev ist vom type net_device allozierst aber tps1_net größe, sind die
>gleich groß, ist das die gleich struktur?
Es wird in dem enc28j60 Treiber genauso gehandhabt. Ich habe mich daran 
mehr oder weniger orientiert. Ich gehe mal davon aus das der einwandfrei 
funktioniert.
(http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/enc28j60.c)

Andreas B. schrieb:
>Ja. tps->tx_ring ist nicht initialisiert, zeigt also nicht auf ein
>struct sk_buff_head. Zumindest sehe ich hier nirgends eine Allokation.
Thanks. Daran hat es gelegen!

Karl Heinz Buchegger schrieb:
>wo genau passiert das in dem von dir geposteten Code?
? In probe.

Karl Heinz Buchegger schrieb:
>eigentlich so lauten sollte
Genauso habe ich es, und so funktioniert es..

von Markus R. (mark989)


Lesenswert?

Karl Heinz Buchegger schrieb:
>..Je mehr ich lese, desto überzeugter bin ich, dass das eigentlich so

Erklär mir mal bitte wo hier der Unterschied liegt, ob man über einen 
Pointer den Inhalt ausliest oder direkt.
Auf jedenfall funkioniert die skb_queue_len-Methode nur so
1
skb_queue_len(&(tps->tx_ring))
also mit struct sk_buff_head  tx_ring; im tps struct.

Nicht jedoch wenn ich über den Pointer zugreife:
1
skb_queue_len(tps->tx_ring)

Was passiert intern genau? Scheint wohl doch einen Unterschied zu machen 
ob man Pointer benutzt oder nicht..

von Andreas B. (andreas_b77)


Lesenswert?

Es macht wenig Sinn, die sk_buff_head noch einmal auszulagern und extra 
zu allokieren — erstens ist sie nicht groß, und zweitens wird sie 
ohnehin immer gebraucht. Da müsste sie immer zusammen mit der tps1_net 
Struktur allokiert werden und zusammen mit ihr freigegeben werden. Kann 
man also genauso gut direkt reinpacken.

Und es gibt keinen Unterschied: Die skb_queue Funktionen verlangen einen 
Pointer auf sk_buff_head Strukturen. Auch sk_buff_init(), das 
initialisiert nur eine existierende Struktur.

von Hans Ulli K. (Gast)


Lesenswert?

ich muss da Leider Karl Heinz Buchegger recht geben

Nach ein wenig suchen
1
struct tps1_net {
2
        struct net_device   *netdev;
3
        struct spi_device   *spi;
4
  struct sk_skbuff   *tx_skb;
5
-  struct sk_buff_head   *tx_ring;
6
+  struct sk_buff_head   tx_ring;
7
  u32 msg_enable;
8
  u8 spi_transfer_buf[1200];
9
};
1
  if(init_gpios()){
2
    printk("GPIO Initialization unsuccessful!\n");
3
    return;
4
  }else{
5
    printk("GPIO Initialization successful!\n");
6
  }
7
8
-  skb_queue_head_init(priv->tx_ring);  
9
+  skb_queue_head_init(&priv->tx_ring);  
10
11
         return 0;
12
error_alloc:

Und für dein skb_queue_len
1
len = skb_queue_len(&priv->tx_ring);

Den Rest kannst du in
include/linux/skbuff.h
lesen

Wie die Queue aufgebaut ist siehe im Device Driver Buch Seite 295
Das steht zwar "Linked List", aber die ersten zwei Elemente von
struct sk_buff_head ist deine Liste

von Karl H. (kbuchegg)


Lesenswert?

Markus R. schrieb:
> Karl Heinz Buchegger schrieb:
>>..Je mehr ich lese, desto überzeugter bin ich, dass das eigentlich so
>
> Erklär mir mal bitte wo hier der Unterschied liegt, ob man über einen
> Pointer den Inhalt ausliest oder direkt.


Du hast eines noch nicht kapiert.
Nur weil eine (oder mehrere) Funktion einen Pointer als Argument will, 
bedeutet das nicht zwangsläufig, dass der Aufrufer auch nur eine 
Pointer-Variable braucht.
Verdammt noch mal. Irgendwo muss es das zugehörige Objekt geben! Lern 
das endlich mal!
1
void foo( int* pI )
2
{
3
  *pI = 5;
4
}
5
6
int main()
7
{
8
  int* Ptr;
9
10
  foo( Ptr );
11
}
das hier geht schief!
Und zwar ganz grauslich! Weil es keinen int gibt, sondern immer nur 
Pointer. Aber irgendwo muss mal ein int im Spiel sein! Denn die 5 müssen 
in einen int bugsiert werden - also muss es auch einen int geben. 
Irgendwo. Nur wo? Im ganzen Programm gibt es keinen!

Das kann jetzt so sein:
1
void foo( int* pI )
2
{
3
  *pI = 5;
4
}
5
6
int main()
7
{
8
  int  derInt;
9
  int* Ptr;
10
11
  Ptr = &derInt;
12
  foo( Ptr );
13
}
so wäre das ok.
Aber wozu das ganze? Wozu brauch ich in main die Pointer-Variable? Eben, 
ich brauch sie überhaupt nicht. Die Adresse des int kann ich auch direkt 
übergeben und spar mir eine Variable ein um die ich mich kümmern muss
1
void foo( int* pI )
2
{
3
  *pI = 5;
4
}
5
6
int main()
7
{
8
  int derInt;
9
10
  foo( &derInt );
11
}
und fertig.
Alles in Butter.
Es gibt einen int und die Funktion kriegt die Adresse von ihm, um mit 
ihm zu arbeiten.

Und bei dir ist das nicht anders. Es reicht nicht, wenn du in deiner 
struct einen Pointer auf einen sbk_queue_head hast. Denn du hast dann 
nur einen Pointer der auf einen skb_queue_head zeigen kann. Du BRAUCHST 
aber ein skb_queue_head OBJEKT! Du hast aber KEINES! Wenn du eines 
hättest, dann könntest du den Pointer drauf zeigen lassen, aber du hast 
keines! Genauso wie ich im ersten Beispeil hier keinen int hatte. Ich 
hatte zwar einen Pointer auf einen int - aber den int selber hatte ich 
nicht.

Klar könnte man in Analogie zum zweiten Beispiel einen extra 
skb_queue_head anlegen und den Pointer in der Struktur drauf zeigen 
lassen. Könnte man. Aber in völliger Analogie zum zweiten Beispiel hier: 
Wozu?
Leg dir doch gleich den skb_head_queue in die Struktur und gut ists. 
Wenn eine Funktion eien Pointer auf ein skb_queue_head haben willst, 
dann gibst du ihm die Adresse davon und gut ists.

> Auf jedenfall funkioniert die skb_queue_len-Methode nur so
>
1
> skb_queue_len(&(tps->tx_ring))
2
>
> also mit struct sk_buff_head  tx_ring; im tps struct.
>
> Nicht jedoch wenn ich über den Pointer zugreife:
>
>
1
> skb_queue_len(tps->tx_ring)
2
>


Du schmeisst Kraut und Rüben durcheinander, dass es nur so eine Freude 
ist (d.h. das ist eigentlich traurig und keine Freude. Wer Kernel-Driver 
programmieren will, für den sollte das alles kein Problem mehr sein. Es 
hilft nichts - man muss sein Handwerrkszeug bzw. grundlegende Techniken 
schon verstehen und nicht einfach nur Unverstandenes aus Tutorien 
"abmalen")

von Markus R. (mark989)


Lesenswert?

OK! Der Grund meines letzten Beitrags.
Nehmen wir mal an ich hab im struct tps noch den sk_buff_head pointer.
Um den auf ein OBJEKT zeigen zu lassen mache ich folgendes:

Alles in der Funktion probe:
1
struct sk_buff_head   ring; //<<-- OBJEKT!!!
2
tps->tx_ring = &ring        //<<-- tps->tx_ring zeigt jetzt auf ein OBJEKT
Macht zwar wenig Sinn da ich es gleich ohne pointer machen könnte, aber 
mich interessiert das Ergebnis.
So. Jetzt initialisier ich es, und frage mal die Länge ab mit
1
skb_queue_len(tps->tx_ring)
Wird auch orgnungsgemäß 0 ausgegeben. Ich probiers nochmal mit einem 
enqueue/dequeue -> funktioniert. Länge 0->1->0, korrekt!

Ab hier in der send-Packet-Funkion(hard_xmit) die vom Kernel aufgerufen 
wird:
Wenn jetzt ein Frame vom Kernel ankommt und der mittels
enqueue(tps->tx_ring, skb) dem tx_ring zugefügt wird, stürzt das system 
ab. Warum?
Dazu gibt skb_queue_len(tps->tx_ring) die Länge -60.....Tausend 
irgendwas aus. Warum? Alle Addressen(von tps, tx_ring, tx_ring.qlen) 
sind mit dem Aufruf aus probe identisch!

Hängt es damit zusammen das jetzt aus einem anderen Thread zugegriffen 
wird?? Kann eigenthlich nicht sein weil ohne einem 
skb_queue_head-Pointer im tps struct funktioniert alles..
Daher die Frage: Wo liegt der Unterschied ob auf ein existierendes(!!) 
Objekt mittels eines Pointer oder direkt zugegriffen wird?
Wenn ich in die Bücherei gehe und das gewolltes Buch von der Rezeption 
bekomme, so sollte es dasselbe sein als wenn ich es mit einem 
Adresskärtchen aus dem Regal hole.

von Hans Ulli K. (Gast)


Lesenswert?

Markus R. schrieb:
>
> Hängt es damit zusammen das jetzt aus einem anderen Thread zugegriffen
> wird?? Kann eigenthlich nicht sein weil ohne einem
> skb_queue_head-Pointer im tps struct funktioniert alles..
> Daher die Frage: Wo liegt der Unterschied ob auf ein existierendes(!!)
> Objekt mittels eines Pointer oder direkt zugegriffen wird?
> Wenn ich in die Bücherei gehe und das gewolltes Buch von der Rezeption
> bekomme, so sollte es dasselbe sein als wenn ich es mit einem
> Adresskärtchen aus dem Regal hole.

Fang mal endlich an Code von anderen Leuten zulesen ...

Ein
1
git grep skb_queue_head_init drivers/net/
gibt mir diesen Output
1
drivers/net/ethernet/marvell/mv643xx_eth.c:
2
        skb_queue_head_init(&txq->tx_skb);
die anderen Zeilen habe ich hier ausgeblendet.
Dann mal nach
1
git grep tx_skb drivers/net/ethernet/marvell
Gibt
1
drivers/net/ethernet/marvell/mv643xx_eth.c:
2
     __skb_queue_tail(&txq->tx_skb, skb);
Wieder die anderen Zeilen brauch' ich nicht

Da ist in
include/linux/skbuff.h definiert
1
static inline void __skb_queue_tail(struct sk_buff_head *list,
2
   struct sk_buff *newsk)
3
{
4
     __skb_queue_before(list, (struct sk_buff *)list, newsk);
5
}
1
static inline void __skb_queue_before(struct sk_buff_head *list,
2
      struct sk_buff *next, struct sk_buff *newsk)
3
{
4
     __skb_insert(newsk, next->prev, next, list);
5
}
In der obigen Funktion wird dein Element angehangen.

Du hast also die falsche Funktion aufgerufen.

von Hans Ulli K. (Gast)


Lesenswert?

Und bevor du noch einen Fehler machst:

Was ist der Unterschied zwischen :
void skb_queue_tail (struct sk_buff_head *list, struct sk_buff *newsk);
und
void __skbqueue_tail (struct sk_buff_head *list, struct sk_buff *newsk);

Welche der beiden Codeabschnitte wird hier funktionieren.
1
static int tps1_send_packet(struct sk_buff *skb, struct net_device *dev)
2
{
3
  printk("send_packet called! \n");
4
  struct tps1_net *priv;
5
  priv = netdev_priv(dev);
6
  
7
  spin_lock_irqsave(&list->lock, flags);        
8
  skb_queue_tail(priv->tx_ring, skb);
9
  spin_unlock_irqrestore(&list->lock, flags);
10
    
11
  kfree_skb( skb );
12
13
         return 0;
14
}
oder
1
static int tps1_send_packet(struct sk_buff *skb, struct net_device *dev)
2
{
3
  printk("send_packet called! \n");
4
  struct tps1_net *priv;
5
  priv = netdev_priv(dev);
6
  
7
  spin_lock_irqsave(&list->lock, flags);        
8
  __skb_queue_tail(priv->tx_ring, skb);
9
  spin_unlock_irqrestore(&list->lock, flags);
10
    
11
  kfree_skb( skb );
12
13
         return 0;
14
}

von Hans Ulli K. (Gast)


Lesenswert?

Hans Ulli Kroll schrieb:
> Und bevor du noch einen Fehler machst:
>
> Was ist der Unterschied zwischen :
> void skb_queue_tail (struct sk_buff_head *list, struct sk_buff *newsk);
> und
> void __skbqueue_tail (struct sk_buff_head *list, struct sk_buff *newsk);
>
> Welche der beiden Codeabschnitte wird hier funktionieren.
>
1
> static int tps1_send_packet(struct sk_buff *skb, struct net_device *dev)
2
> {
3
>   printk("send_packet called! \n");
4
>   struct tps1_net *priv;
5
>   priv = netdev_priv(dev);
6
> 
7
>   spin_lock_irqsave(&list->lock, flags);
8
>   skb_queue_tail(priv->tx_ring, skb);
9
>   spin_unlock_irqrestore(&list->lock, flags);
10
> 
11
>   kfree_skb( skb );
12
> 
13
>          return 0;
14
> }
15
>
> oder
>
1
> static int tps1_send_packet(struct sk_buff *skb, struct net_device *dev)
2
> {
3
>   printk("send_packet called! \n");
4
>   struct tps1_net *priv;
5
>   priv = netdev_priv(dev);
6
> 
7
>   spin_lock_irqsave(&list->lock, flags);
8
>   __skb_queue_tail(priv->tx_ring, skb);
9
>   spin_unlock_irqrestore(&list->lock, flags);
10
> 
11
>   kfree_skb( skb );
12
> 
13
>          return 0;
14
> }
15
>

Ich habe mich da beim letzten Post vertan ...
1
static int tps1_send_packet(struct sk_buff *skb, struct net_device *dev)
2
{
3
 printk("send_packet called! \n");
4
  struct tps1_net *priv;
5
  priv = netdev_priv(dev);
6
7
  spin_lock_irqsave(&priv->tx_ring->lock, flags);
8
  __skb_queue_tail(priv->tx_ring, skb);
9
  spin_unlock_irqrestore(&priv->tx_ring->lock, flags);
10
11
  kfree_skb( skb );
12
13
  return 0;
14
}
oder
1
static int tps1_send_packet(struct sk_buff *skb, struct net_device *dev)
2
{
3
 printk("send_packet called! \n");
4
  struct tps1_net *priv;
5
  priv = netdev_priv(dev);
6
7
  spin_lock_irqsave(&priv->tx_ring->lock, flags);
8
  skb_queue_tail(priv->tx_ring, skb);
9
  spin_unlock_irqrestore(&priv->tx_ring->lock, flags);
10
11
  kfree_skb( skb );
12
13
  return 0;
14
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.