2013-06-26 27 views
5

Mi piacerebbe sapere se è possibile fare memoria per bit invece che per byte?è possibile fare memcpy in bit invece che in byte?

Sto scrivendo un codice C per il frame Ethernet con tag VLAN, in cui ho bisogno di riempire diversi valori per gli attributi di intestazione VLAN (PCP-3bit, DEI-1 bit, VID-12bit).

Come posso fare memcpy a quei bit, o qualsiasi altra possibilità per riempire i valori di quegli attributi in bit.

Grazie in anticipo!

+0

La domanda più importante è se si prevede che i bit si spostino in relazione ai limiti di 8 bit come parte della copia; e ti aspetti che i bit possano sovrapporsi? –

+1

memcpy copia n 'byte' dall'origine alla destinazione.Non puoi usare 'memcpy' per bit. –

+0

Ho bisogno di questa funzionalità per lo stesso motivo, per favore fornisci una risposta su come hai risolto questo problema. – jwbensley

risposta

1

Se è necessario compilare i campi, è possibile utilizzare C bit-fields con un struct, come questo:

struct box_props { 
    unsigned first : 1; 
    unsigned second : 3; 
    unsigned : 4; 
}; 

Dove 1, per esempio, significa che il campo è lungo 1 bit. L'ultimo campo (senza nome) significa: imbottitura a 4 bit.

Definire struct, memcpy e leggere i campi come se fossero unsigned. Lo stesso per la scrittura.

NOTA: il pad sempre su byte intero o memcpy potrebbe avere effetti indesiderati.

+1

Si noti che questo è interamente definito dall'implementazione. Vedi [questa risposta] (http://stackoverflow.com/a/1490669/188535) per i dettagli, ma in fondo è l'ordine e l'imballaggio che non è portabile. – detly

+0

Grazie ... Proverò con il metodo della struttura. – arr

+0

Ma tieni a mente quello che hanno detto le altre persone e la risposta SO collegata da @detly (credo che dovrei aggiornare il mio C-fu): questo non è portatile e potrebbero nascere bug strani. In realtà, Pascal ti ha fornito la risposta canonica. –

6

No. I bit non sono indirizzabili (ovvero non è possibile leggerli e solo loro direttamente dalla memoria.) Non hanno indirizzo. Solo byte hanno indirizzi).

È necessario leggere il byte o la parola che contiene i bit a cui si è interessati e fare il masking da soli.

1

Ho eseguito la codifica VLAN 802.1Q di frame per un client in cui disponevano solo di 802.3 frame Ethernet ma volevo eseguire la migrazione su 802.1Q in quanto era installato un nuovo switch VLAN consapevole.

Innanzitutto, non è possibile copiare i bit. Abbiamo copiato il tag in byte usando memcpy.

Illustrazione (vedi Wikipedia per le descrizioni dei campi): -

VLAN tag = 4 byte; composto da TPID (2 byte) e TCI (2 byte).

TPID è semplice ed è sempre 0x8100 che indica un frame con tag VLAN.

TCI è costituito da PCP-3 bit, DEI-1 bit, VID-12 bit. Ripartizione del TCI in nibbles, cioè 4 bit. Per impostazione predefinita, il nibble (PCP + DEI) = 0x0 assumendo la priorità è disabilitato e DEI = 0. I restanti 3-nibbles (12 bit) sono per l'ID VLAN stesso. Supponi di voler taggare un frame per VLAN-ID = 123. In esadecimale sarà = 0x07B.

Raggruppa insieme i bocconcini e lì hai il tuo campo TCI a 2 byte che ora può essere visto come 0x007B.

Quindi è possibile effettuare le seguenti operazioni. (codice non compilato)

unsigned short int vlanTPID, vlanTCI; 
unsigned char  *dest, *src; 

// Set the VLAN Tag 
vlanTPID = 0x8100; 
vlanTCI = 0x007B; 

// Pointer to the TPID position of ethernet frame 
dest = &vlanTagPosition; 
src = &vlanTPID; 
memcpy(dest, src, sizeof(vlanTPID)); 

// Increment dest pointer by 2 bytes to insert TCI in the ethernet frame 
dest += 2; 
src = &vlanTCI; 
memcpy(dest, src, sizeof(vlanTCI)); 
+0

Questa è la parte facile dove PCP e DEI sono 0, ora assumiamo un vlanID di 4011 e un PCP 7 con DEI 0, mi piacerebbe vederlo (perché sono davvero alle prese con questo!). – jwbensley

+0

| 1 1 1 0 | 1 1 1 1 | 1 0 1 0 | 1 0 1 1 | - Come ho detto, è necessario immaginare il campo TCI come 16-bit o 4-nibbles. Il primo nibble è PCP + DEI = 7 e i restanti 3-nibbles sono VLAN-ID = 4011. Una volta convertiti i bit binari in esadecimale, il campo TCI sarà 0xEFAB. – ritwick87