
「フリトスのようなコードモンキー
タブとマウンテンデューのようなコードモンキー
コードモンキー非常に単純な男
大きな暖かいファジーな秘密の心で:
あなたのようなコードモンキー
あなたのようなコードモンキー»
-ジョナサンコールトン-コードモンキー
多くの人がジョナサンコールトンのこのシックな歌に精通しており、「ロブはコードモンキーは非常に勤勉だ」と言うが、「彼の出力は悪臭を放ち」、「彼のコードは「機能的」でも「エレガント」でもない」という状況を知っています。
非常に便利なソフトウェアを提供してくれたC言語は、JavaやC#などの高レベルの巨人によってデスクトップとエンタープライズから徐々に絞り出され、システムプログラミングのニッチを占めました。 そして、すべてがうまくいくだろうが、システムエンジニアは非常に
今日は、Cシステムプログラミングの奥深さから学んだいくつかの優れた実践についてお話します。 行こう
項目は、最も基本的で明白な(C言語の初心者向け)から、最も具体的で有用なものまであります。 あなたがそれを知っていると感じたら-スクロールしてください。
実践I:統一されたコードスタイルと「良いトーン」の基本原則を順守する
関数は引数としてINPUT変数を受け取り、それをIncomingValues配列に解析し、result_to_return?を返しますか? バイコードは取っておきましょう!
初心者が最初に与えることは、特定のアプリケーション内でコードを記述する単一のスタイルを守らないことです。 次は「マナー」のルールを無視します。
Cコードを記述するための最も一般的なガイドラインの一部を次に示します。
- マクロとマクロ関数の名前は大文字で表記され、名前の単語は下線で互いに区切られています。
#define MAX_ARRAY_SIZE 32 #define INCORRECT_VALUE -1 #define IPC_FIND_NODE(x) ipc_find_node(config.x)
- ,
int my_int_variable = 0; char *hello_str = "hello_habrahabr"; pid_t current_pid = fork();
, . , camelCase PascalCase .
UPD: fogree , PascalCase camelCase.
- , , — .
, , . .
— a, b, c — ( ). — .
- ( - ) , , .
, : PascalCase under_score, .
/* */ static void dgtprint(char *str) { int i; for (i = 0; i < strlen(str); i++) { if (isdigit(str[i])) printf("%c", str[i]); else print("_"); } } /* */ /* PascalCase */ void EnableAllVlans(struct vlan_cfg *vp) { int i; for (i = 0; i < VLAN_COUNT; i++) { EnableVlanByProto(vp.vlan[i]); } } /* under_score */ void enable_all_vlans(struct vlan_cfg *vp) { int i; for (i = 0; i < VLAN_COUNT; i++) { enable_vlan_by_proto(vp.vlan[i]); } }
- i, j, k —
int array[MAX_ARRAY_SIZE] = arrinit(); register int i, j, k; for (i = 0; i < MAX_ARRAY_SIZE; i++) for (j = 0; j < MAX_ARRAY_SIZE; j++) for (k = MAX_ARRAY_SIZE; k >= 0; k--) dosmthng(i, j, k, array[i]);
-
if (condition) { dosmthng(); } else { dont_do_something(); } /* */ if (condition) { dosmthng(); } else { dont_do_something(); } /* , */ if (condition) { dosmthng(); } else { dont_do_something(); } /* */ /* , , */ if (condition) { dosmthng(); } else { dont_do_something(); }
- . , .
. , — NULL:
int counter = 0, start_position = 0, unknown_position = 0; struct dhcp_header * dhcp = NULL, * dhcp_temp = NULL; char input_string[32] = { 0 };
, ?
. ( ) ( gdb), . (, « »). .
- .
— , .
— , . — , - , .
, — , , , , , .
/* 1, , * , 0, . */ static int CheckModemConnection() { int i = 0; /* - */ if (CHECK_CFG_STR(Network.LanIpAddress) || CHECK_CFG_STR(Network.LanNetmask)) return 1; for(i = 0; i < MAX_MODEM_IDX; i++) { if (CHECK_CFG_INT(Modems.Modem[i].Proto) || CHECK_CFG_INT(Modems.Modem[i].MTU) || CHECK_CFG_STR(Modems.Modem[i].Username) || CHECK_CFG_STR(Modems.Modem[i].Password) || CHECK_CFG_STR(Modems.Modem[i].Number) || CHECK_CFG_STR(Modems.Modem[i].AdditionalParams) || CHECK_CFG_STR(Modems.Modem[i].PIN) || CHECK_CFG_STR(Modems.Modem[i].MRU) || CHECK_CFG_STR(Modems.Modem[i].PppoeIdle) || CHECK_CFG_STR(Modems.Modem[i].USBPort) || CHECK_CFG_STR(Reservation.Prefer) || CHECK_CFG_STR(Modems.Modem[i].PppoeConnectType) || CHECK_CFG_INT(Modems.Mode) || CHECK_CFG_INT(Aggregation.usb1) || CHECK_CFG_INT(Aggregation.usb2)) return 1; } return 0; }
( RedMine), , . - - « ?», . , , .
/* Muraviyov: #66770 */
P.S. : , , , Code Style, . - .
II:
— .
, , , , :
- , , .
file1.c, mySUPER_COOL_header.h ..
main.c — , graph_const.h — .
- include.
:
- project/
- common.c
- common.h
- main.c
- network.h
- networking.c
- networking_v6.c
- packet.c
- packet.h
- Makefile
, ? , :
- project/
- include/
- common.h
- network.h
- packet.h
- common.c
- main.c
- networking.c
- networking_v6.c
- packet.c
- Makefile
- include/
, include . Makefile (include , Makefile):
@$(CC) $(OBJS) -o networkd -L$(ROMFS)/lib -linteraction -Wall -lpthread -I ./include
- project/
- .c .
, , // — . , — .
- — , . Makefile :
.PHONY clean build build: cd sound/ && make clean && make cd graphics/ && make clean && make cd engine/ && make clean && make sound: cd sound/ && make clean && make graphics: cd graphics/ && make clean && make engine: cd engine/ && make clean && make clean: cd sound/ && make clean cd engine/ && make clean cd greaphics/ && make clean
III: -
- (-) . , , , errno .
( — ), , «» . -, , , .
— . , (+ ) .
. — :
int sock_one = 0, sock_two = 0, sock_three = 0;
/* , ,
*
*/
if ((socket_one = socket(AF_INET , SOCK_STREAM , 0)) <= 0) {
perror("socket one");
exit(EXIT_ERROR_CODE);
}
if ((socket_two = socket(AF_INET , SOCK_DGRAM , 0)) <= 0) {
perror("socket two");
exit(EXIT_ERROR_CODE);
}
if ((socket_three = socket(PF_INET , SOCK_RAW , 0)) <= 0) {
perror("socket three");
exit(EXIT_ERROR_CODE);
}
, , ? .
/* - ... */
int Socket(int domain, int type, int proto) {
int desk = socket(domain, type, proto);
if (desk <= 0) {
perror("socket");
exit(EXIT_ERROR_CODE);
}
return desk;
}
/* ......... n - ......... */
int socket_one = 0, socket_two = 0, soket_three = 0;
socket_one = Socket(AF_INET , SOCK_STREAM , 0);
socket_two = Socket(AF_INET , SOCK_DGRAM , 0);
socket_three = Socket(PF_INET , SOCK_RAW , 0);
, - ( «» ), .
, . , .
, , , . — :)
IV: keywords
keywords . , , . , — , .
, , . , , . :
- register — , . register - .
register byte i = 0; for (i; i < 256; i++) check_value(i);
- restrict — (, , ), , . , , - . — , .
void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val);
- volatile — , . , , dead code (, ), , .
int var = 1; if (!var) /* 2 */ dosmthng(); volatile int var = 1; if (!var) /* - */ dosmthng();
. — .
V: . valgrind.
, , , .
Valgrind — , , . , , , , , , . .
+ .
.
VI: ,
busybox 1.21. , busybox, -.
UPD: «» busybox. themiron , , — , . «» busybox, .
, busybox.
busybox , . , — .
busybox. udhcpc — DHCP :
- , .
DHCP RFC, dhcp-. , , . — , , (DHCP- <-> DHCP-).
( networking/udhcp/common.h)
struct dhcp_packet { uint8_t op; /* BOOTREQUEST or BOOTREPLY */ uint8_t htype; /* hardware address type. 1 = 10mb ethernet */ uint8_t hlen; /* hardware address length */ uint8_t hops; /* used by relay agents only */ uint32_t xid; /* unique id */ uint16_t secs; /* elapsed since client began acquisition/renewal */ uint16_t flags; /* only one flag so far: */ #define BROADCAST_FLAG 0x8000 /* "I need broadcast replies" */ uint32_t ciaddr; /* client IP (if client is in BOUND, RENEW or REBINDING state) */ uint32_t yiaddr; /* 'your' (client) IP address */ /* IP address of next server to use in bootstrap, returned in DHCPOFFER, DHCPACK by server */ uint32_t siaddr_nip; uint32_t gateway_nip; /* relay agent IP address */ uint8_t chaddr[16]; /* link-layer client hardware address (MAC) */ uint8_t sname[64]; /* server host name (ASCIZ) */ uint8_t file[128]; /* boot file name (ASCIZ) */ uint32_t cookie; /* fixed first four option bytes (99,130,83,99 dec) */ uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS]; } PACKED;
- .
, .. .
: , .
( networking/udhcp/common.h)
struct dhcp_packet { uint8_t op; /* BOOTREQUEST or BOOTREPLY */ uint8_t htype; /* hardware address type. 1 = 10mb ethernet */ uint8_t hlen; /* hardware address length */ uint8_t hops; /* used by relay agents only */ uint32_t xid; /* unique id */ uint16_t secs; /* elapsed since client began acquisition/renewal */ uint16_t flags; /* only one flag so far: */ #define BROADCAST_FLAG 0x8000 /* "I need broadcast replies" */ uint32_t ciaddr; /* client IP (if client is in BOUND, RENEW or REBINDING state) */ uint32_t yiaddr; /* 'your' (client) IP address */ /* IP address of next server to use in bootstrap, returned in DHCPOFFER, DHCPACK by server */ uint32_t siaddr_nip; uint32_t gateway_nip; /* relay agent IP address */ uint8_t chaddr[16]; /* link-layer client hardware address (MAC) */ uint8_t sname[64]; /* server host name (ASCIZ) */ uint8_t file[128]; /* boot file name (ASCIZ) */ uint32_t cookie; /* fixed first four option bytes (99,130,83,99 dec) */ uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS]; } PACKED; #define DHCP_PKT_SNAME_LEN 64 #define DHCP_PKT_FILE_LEN 128 #define DHCP_PKT_SNAME_LEN_STR "64" #define DHCP_PKT_FILE_LEN_STR "128" struct ip_udp_dhcp_packet { struct iphdr ip; struct udphdr udp; struct dhcp_packet data; } PACKED; struct udp_dhcp_packet { struct udphdr udp; struct dhcp_packet data; } PACKED; enum { IP_UDP_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, UDP_DHCP_SIZE = sizeof(struct udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, DHCP_SIZE = sizeof(struct dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, };
, , :
( networking/udhcp/common.h)
unsigned FAST_FUNC udhcp_option_idx(const char *name); uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; int udhcp_end_option(uint8_t *optionptr) FAST_FUNC; void udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt) FAST_FUNC; void udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t data) FAST_FUNC; #if ENABLE_FEATURE_UDHCP_RFC3397 char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) FAST_FUNC; #endif struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code) FAST_FUNC;
-
udhcpc , . , .
— , . , « ?» . .
— , , .
( networking/udhcp/common.h)
#define DHCP_PADDING 0x00 #define DHCP_SUBNET 0x01 //#define DHCP_TIME_OFFSET 0x02 /* (localtime - UTC_time) in seconds. signed */ //#define DHCP_ROUTER 0x03 //#define DHCP_TIME_SERVER 0x04 /* RFC 868 time server (32-bit, 0 = 1.1.1900) */ //#define DHCP_NAME_SERVER 0x05 /* IEN 116 _really_ ancient kind of NS */ //#define DHCP_DNS_SERVER 0x06 //#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) //#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */ //#define DHCP_LPR_SERVER 0x09 #define DHCP_HOST_NAME 0x0c /* either client informs server or server gives name to client */ //#define DHCP_BOOT_SIZE 0x0d //#define DHCP_DOMAIN_NAME 0x0f /* server gives domain suffix */ //#define DHCP_SWAP_SERVER 0x10 //#define DHCP_ROOT_PATH 0x11 //#define DHCP_IP_TTL 0x17 //#define DHCP_MTU 0x1a //#define DHCP_BROADCAST 0x1c //#define DHCP_ROUTES 0x21 //#define DHCP_NIS_DOMAIN 0x28 //#define DHCP_NIS_SERVER 0x29 //#define DHCP_NTP_SERVER 0x2a //#define DHCP_WINS_SERVER 0x2c #define DHCP_REQUESTED_IP 0x32 /* sent by client if specific IP is wanted */ #define DHCP_LEASE_TIME 0x33 #define DHCP_OPTION_OVERLOAD 0x34 #define DHCP_MESSAGE_TYPE 0x35 #define DHCP_SERVER_ID 0x36 /* by default server's IP */ #define DHCP_PARAM_REQ 0x37 /* list of options client wants */ //#define DHCP_ERR_MESSAGE 0x38 /* error message when sending NAK etc */ #define DHCP_MAX_SIZE 0x39 #define DHCP_VENDOR 0x3c /* client's vendor (a string) */ #define DHCP_CLIENT_ID 0x3d /* by default client's MAC addr, but may be arbitrarily long */ //#define DHCP_TFTP_SERVER_NAME 0x42 /* same as 'sname' field */ //#define DHCP_BOOT_FILE 0x43 /* same as 'file' field */ //#define DHCP_USER_CLASS 0x4d /* RFC 3004. set of LASCII strings. "I am a printer" etc */ #define DHCP_FQDN 0x51 /* client asks to update DNS to map its FQDN to its new IP */ //#define DHCP_DOMAIN_SEARCH 0x77 /* RFC 3397. set of ASCIZ string, DNS-style compressed */ //#define DHCP_SIP_SERVERS 0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ #define DHCP_VLAN_ID 0x84 /* 802.1P VLAN ID */ #define DHCP_VLAN_PRIORITY 0x85 /* 802.1Q VLAN priority */ //#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ #define DHCP_END 0xff
- .
, . : , n ( n — ), , , , . . , :
( networking/udhcp/packet.c)
/* Construct a ip/udp header for a packet, send packet */ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, uint32_t source_nip, int source_port, uint32_t dest_nip, int dest_port, const uint8_t *dest_arp, int ifindex) { struct sockaddr_ll dest_sll; struct ip_udp_dhcp_packet packet; unsigned padding; int fd; int result = -1; const char *msg; fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); if (fd < 0) { msg = "socket(%s)"; goto ret_msg; } memset(&dest_sll, 0, sizeof(dest_sll)); memset(&packet, 0, offsetof(struct ip_udp_dhcp_packet, data)); packet.data = *dhcp_pkt; /* struct copy */ dest_sll.sll_family = AF_PACKET; dest_sll.sll_protocol = htons(ETH_P_IP); dest_sll.sll_ifindex = ifindex; dest_sll.sll_halen = 6; memcpy(dest_sll.sll_addr, dest_arp, 6); if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) { msg = "bind(%s)"; goto ret_close; } /* We were sending full-sized DHCP packets (zero padded), * but some badly configured servers were seen dropping them. * Apparently they drop all DHCP packets >576 *ethernet* octets big, * whereas they may only drop packets >576 *IP* octets big * (which for typical Ethernet II means 590 octets: 6+6+2 + 576). * * In order to work with those buggy servers, * we truncate packets after end option byte. */ padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(packet.data.options); packet.ip.protocol = IPPROTO_UDP; packet.ip.saddr = source_nip; packet.ip.daddr = dest_nip; packet.udp.source = htons(source_port); packet.udp.dest = htons(dest_port); /* size, excluding IP header: */ packet.udp.len = htons(UDP_DHCP_SIZE - padding); /* for UDP checksumming, ip.len is set to UDP packet len */ packet.ip.tot_len = packet.udp.len; packet.udp.check = inet_cksum((uint16_t *)&packet, IP_UDP_DHCP_SIZE - padding); /* but for sending, it is set to IP packet len */ packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding); packet.ip.ihl = sizeof(packet.ip) >> 2; packet.ip.version = IPVERSION; packet.ip.ttl = IPDEFTTL; packet.ip.check = inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip)); udhcp_dump_packet(dhcp_pkt); result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0, (struct sockaddr *) &dest_sll, sizeof(dest_sll)); msg = "sendto"; ret_close: close(fd); if (result < 0) { ret_msg: bb_perror_msg(msg, "PACKET"); } return result; }
dhcp IP . (BROADCAST) .
— , broadcast. , , , , , . :
( networking/udhcp/dhcpc.c)
static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet) { return udhcp_send_raw_packet(packet, /*src*/ INADDR_ANY, CLIENT_PORT, /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); }
, , , , . udhcp_send_raw_packet, .
, , , . .
, . , . . .
.
, !