Les langages de programmation de haut niveau sont populaires, mais il existe des domaines dans lesquels vous devrez utiliser des implémentations de bibliothèques non gérées. Cela peut être un appel à des fonctions spécifiques du système d'exploitation, à un accès de bas niveau aux périphériques, au besoin de performances dans les algorithmes, etc. Sous la coupe, je vais vous dire ce que vous pouvez rencontrer en voyageant en code non géré et ce que vous devez emporter avec vous.
Vous vous trouvez à la porte de votre IDE confortable, et vous n'êtes pas du tout tenté d'aller dans le monde du code source, où il fait sombre et où rien n'est clair. Pour le succès de l'entreprise, tout d'abord, vous devez vous procurer une carte - une description des en-têtes de la bibliothèque s'affichera, et il est préférable d'avoir une documentation complète. Cela ressemble généralement à ceci:
...
#include <linux/netfilter_ipv4/ip_tables.h>
#include <libiptc/xtcshared.h>
#ifdef __cplusplus
extern "C" {
#endif
#define iptc_handle xtc_handle
#define ipt_chainlabel xt_chainlabel
#define IPTC_LABEL_ACCEPT "ACCEPT"
#define IPTC_LABEL_DROP "DROP"
#define IPTC_LABEL_QUEUE "QUEUE"
#define IPTC_LABEL_RETURN "RETURN"
/* Does this chain exist? */
int iptc_is_chain(const char *chain, struct xtc_handle *const handle);
/* Take a snapshot of the rules. Returns NULL on error. */
struct xtc_handle *iptc_init(const char *tablename);
/* Cleanup after iptc_init(). */
void iptc_free(struct xtc_handle *h);
...
Disons que vous avez de la chance et que la documentation est là. Il décrit les signatures de fonction, les structures utilisées, les alias et les références à d'autres en-têtes utilisés. La première quête est de trouver la bibliothèque dans le système d'exploitation. Son nom peut différer de ce qui est attendu:
~$ find /usr/lib/x86_64-linux-gnu/ -maxdepth 1 -name 'libip*'
/usr/lib/x86_64-linux-gnu/libip6tc.so.0.1.0
/usr/lib/x86_64-linux-gnu/libip4tc.so
/usr/lib/x86_64-linux-gnu/libiptc.so.0
/usr/lib/x86_64-linux-gnu/libip4tc.so.0.1.0
/usr/lib/x86_64-linux-gnu/libip6tc.so.0
/usr/lib/x86_64-linux-gnu/libiptc.so.0.0.0
/usr/lib/x86_64-linux-gnu/libip4tc.so.0
/usr/lib/x86_64-linux-gnu/libiptc.so
/usr/lib/x86_64-linux-gnu/libip6tc.so
Le suffixe numérique signifie différentes versions de bibliothèques. En général, nous avons besoin de l'original libip4tc.so. Vous pouvez regarder à l'intérieur d'un seul œil et vous assurer que cela en vaut la peine:
~$ nm -D /usr/lib/x86_64-linux-gnu/libip4tc.so ... 0000000000206230 D _edata 0000000000206240 B _end U __errno_location U fcntl 000000000000464c T _fini U __fprintf_chk U free U getsockopt w __gmon_start__ 0000000000001440 T _init 0000000000003c80 T iptc_append_entry 0000000000003700 T iptc_builtin 0000000000004640 T iptc_check_entry 0000000000003100 T iptc_commit 0000000000002ff0 T iptc_create_chain 00000000000043f0 T iptc_delete_chain ...
, , , . :
public static class Libiptc4
{
/* Prototype: iptc_handle_t iptc_init(const char *tablename) */
[DllImport("libip4tc.so")]
public static extern IntPtr iptc_init(string tablename);
}
/* Prototype: iptc_handle_t iptc_init(const char *tablename) */
[DllImport("libip4tc.so")]
public static extern IntPtr iptc_init(IntPtr tblPtr);
...
var tblPtr = Marshal.StringToHGlobalAnsi("filter");
var _handle = Libiptc4.iptc_init_ptr(tblPtr);
Marshal.FreeHGlobal(tblPtr);
.
, , , , .
, : . :
struct ipt_entry {
struct ipt_ip ip;
/* Mark with fields that we care about. */
unsigned int nfcache;
/* Size of ipt_entry + matches */
__u16 target_offset;
/* Size of ipt_entry + matches + target */
__u16 next_offset;
/* Back pointer */
unsigned int comefrom;
/* Packet and byte counters. */
struct xt_counters counters;
/* The matches (if any), then the target. */
unsigned char elems[0];
};
unsigned char elems[0]
. , , . :
*******************************************
* ip_entry *
* 112 bytes *
*******************************************
* matches *
* target_offset - 112 bytes *
*******************************************
* target *
* next_offset - target_offset - 112 bytes *
*******************************************
(matches
target
) ip_entry
. :
.
.
, , . ipt_entry
:
[StructLayout(LayoutKind.Sequential)]
public struct IptEntry
{
public IptIp ip;
public uint nfcache;
public ushort target_offset;
public ushort next_offset;
public uint comefrom;
public IptCounters counters;
};
Marshal.SizeOf<IptEntry>()
112 . matches
target
( ). : libiptc
8 ( long
), . , . :
static readonly int _WORDLEN = Marshal.SizeOf<long>();
public static int Align(int size)
{
return ((size + (_WORDLEN - 1)) & ~(_WORDLEN - 1));
}
, entry.target_offset
entry.next_offset
, :
IntPtr entryPtr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr<IptEntry>(entryPtr, entry, false);
Marshal.StructureToPtr<Match>(entryPtr + 112, match, false);
: , , :
var entry = Marshal.PtrToStructure<IptEntry>(point);
var match = Marshal.PtrToStructure<Match>(point + 112)
, union:
struct xt_entry_match {
union {
struct {
__u16 match_size;
/* Used by userspace */
char name[XT_EXTENSION_MAXNAMELEN];
__u8 revision;
} user;
struct {
__u16 match_size;
/* Used inside the kernel */
struct xt_match *match;
} kernel;
/* Total length */
__u16 match_size;
} u;
unsigned char data[0];
};
:
#define XT_EXTENSION_MAXNAMELEN 29
...
char name [XT_EXTENSION_MAXNAMELEN]
. header .
, . ushort, uint long , . . : , . . . :
byte [] convArray = BitConverter.GetBytes(value);
Array.Reverse(convArray);
ushort reverseEndian = BitConverter.ToUInt16(convArray,0);
ushort reverseEndian = (ushort)((value << 8) | (value >> 8));
. unmanaged code . /, errno. . , :
[DllImport("libip4tc.so", SetLastError = true)]
, , :
int errno = Marshal.GetLastWin32Error();
var errPtr = Libiptc4.iptc_strerror(errno);
string errStr = Marshal.PtrToStringAnsi(errPtr);
Linux c net.core (, /). : -, 32/64 , Windows . .
Ceci conclut notre voyage. J'ajouterai que l'utilisation de bibliothèques de bas niveau semble être une approche difficile et imprévisible en termes de succès. Le manque de documentation et les interactions complexes peuvent être effrayants. Cependant, c'est parfois le seul moyen d'obtenir le résultat souhaité.