From d4a286bdfd61be9381b0c5199c0a637b8372df1c Mon Sep 17 00:00:00 2001 From: Guo Wenxue <guowenxue@gmail.com> Date: Thu, 08 Nov 2018 11:00:27 +0800 Subject: [PATCH] Add Ch3_fork sample code --- ch3_fork/fork_exec.c | 96 ++++++++++ ch3_fork/memory_layout.c | 42 ++++ ch3_fork/socket_server.c | 162 ++++++++++++++++++ ch3_fork/popen.c | 88 +++++++++ ch3_fork/fork.c | 28 +++ ch3_fork/fork_var.c | 109 ++++++++++++ 6 files changed, 525 insertions(+), 0 deletions(-) diff --git a/ch3_fork/fork.c b/ch3_fork/fork.c new file mode 100644 index 0000000..4dbb728 --- /dev/null +++ b/ch3_fork/fork.c @@ -0,0 +1,28 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +int main(int argc, char **argv) +{ + pid_t pid; + + printf("Parent process PID[%d] start running...\n", getpid() ); + + pid = fork(); + if(pid < 0) + { + printf("fork() create child process failure: %s\n", strerror(errno)); + return -1; + } + else if( pid == 0 ) + { + printf("Child process PID[%d] start running, my parent PID is [%d]\n", getpid(), getppid()); + return 0; + } + else // if( pid > 0 ) + { + printf("Parent process PID[%d] continue running, and child process PID is [%d]\n", getpid(), pid); + return 0; + } +} diff --git a/ch3_fork/fork_exec.c b/ch3_fork/fork_exec.c new file mode 100644 index 0000000..e009f47 --- /dev/null +++ b/ch3_fork/fork_exec.c @@ -0,0 +1,96 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <ctype.h> + +#define TMP_FILE "/tmp/.ifconfig.log" + +int main(int argc, char **argv) +{ + pid_t pid; + int fd; + char buf[1024]; + int rv; + char *ptr; + FILE *fp; + char *ip_start; + char *ip_end; + char ipaddr[16]; + + if( (fd=open(TMP_FILE, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0 ) + { + printf("Redirect standard output to file failure: %s\n", strerror(errno)); + return -1; + } + + pid = fork(); + if(pid < 0) + { + printf("fork() create child process failure: %s\n", strerror(errno)); + return -1; + } + else if( pid == 0 ) + { + printf("Child process start excute ifconfig program\n"); + dup2(fd, STDOUT_FILENO); + execl("/sbin/ifconfig", "ifconfig", "eth0", NULL); + printf("Child process excute another program, will not return here. Return here means execl() error\n"); + return -1; + } + else + { + sleep(3); + } + + memset(buf, 0, sizeof(buf)); + + rv=read(fd, buf, sizeof(buf)); + printf("Read %d bytes data dierectly read after child process write\n", rv); + + memset(buf, 0, sizeof(buf)); + lseek(fd, 0, SEEK_SET); + rv=read(fd, buf, sizeof(buf)); + printf("Read %d bytes data after lseek:\n %s", rv, buf); + + fp = fdopen(fd, "r"); + fseek(fp, 0, SEEK_SET); + + while( fgets(buf, sizeof(buf), fp) ) + { + if( strstr(buf, "netmask") ) + { + ptr=strstr(buf, "inet"); + if( !ptr ) + { + break; + } + ptr += strlen("inet"); + + while( isblank(*ptr) ) + ptr++; + + ip_start = ptr; + + while( !isblank(*ptr) ) + ptr++; + + ip_end = ptr; + + memset(ipaddr, 0, sizeof(ipaddr)); + memcpy(ipaddr, ip_start, ip_end-ip_start); + + break; + } + } + + printf("Parser and get IP address: %s\n", ipaddr); + + fclose(fp); + unlink(TMP_FILE); + + return 0; +} diff --git a/ch3_fork/fork_var.c b/ch3_fork/fork_var.c new file mode 100644 index 0000000..1489039 --- /dev/null +++ b/ch3_fork/fork_var.c @@ -0,0 +1,109 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <ctype.h> + +#define TMP_FILE "/tmp/.ifconfig.log" + +int main(int argc, char **argv) +{ + pid_t pid; + int fd; + char buf[1024]; + int rv; + char *ptr; + FILE *fp; + char *ip_start; + char *ip_end; + char ipaddr[16]; + + if( (fd=open(TMP_FILE, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0 ) + { + printf("Redirect standard output to file failure: %s\n", strerror(errno)); + return -1; + } + + pid = fork(); + if(pid < 0) + { + printf("fork() create child process failure: %s\n", strerror(errno)); + return -1; + } + else if( pid == 0 ) + { + printf("Child process start excute ifconfig program\n"); + dup2(fd, STDOUT_FILENO); + execl("/sbin/ifconfig", "ifconfig", "eth0", NULL); + printf("Child process start excute ifconfig program over\n"); + return 0; + } + else + { + sleep(3); + } + + memset(buf, 0, sizeof(buf)); + + rv=read(fd, buf, sizeof(buf)); + printf("Read %d bytes data dierectly read after child process write\n", rv); + + lseek(fd, 0, SEEK_SET); + rv=read(fd, buf, sizeof(buf)); + printf("Read %d bytes data after lseek:\n %s\n ", rv, buf); + + fp = fdopen(fd, "r"); + fseek(fp, 0, SEEK_SET); + + memset(buf, 0, sizeof(buf)); + + rv=read(fd, buf, sizeof(buf)); + printf("Read %d bytes data dierectly read after child process write\n", rv); + printf("Read %d bytes data dierectly read after child process write\n", rv); + + lseek(fd, 0, SEEK_SET); + rv=read(fd, buf, sizeof(buf)); + printf("Read %d bytes data after lseek:\n %s\n ", rv, buf); + + fp = fdopen(fd, "r"); + fseek(fp, 0, SEEK_SET); + + while( fgets(buf, sizeof(buf), fp) ) + { + if( strstr(buf, "netmask") ) + { + ptr=strstr(buf, "inet"); + if( !ptr ) + { + break; + } + ptr += strlen("inet"); + + while( isblank(*ptr) ) + ptr++; + + ip_start = ptr; + + while( !isblank(*ptr) ) + ptr++; + + ip_end = ptr; + + memset(ipaddr, 0, sizeof(ipaddr)); + memcpy(ipaddr, ip_start, ip_end-ip_start); + + break; + } + } + + printf("Parser and get IP address: %s\n", ipaddr); + + fclose(fp); + + unlink(TMP_FILE); + + return 0; +} diff --git a/ch3_fork/memory_layout.c b/ch3_fork/memory_layout.c new file mode 100644 index 0000000..5a786cd --- /dev/null +++ b/ch3_fork/memory_layout.c @@ -0,0 +1,42 @@ +#include <stdio.h> +#include <stdlib.h> + +int g_var1; +int g_var2=20; + +int main(int argc, char **argv) +{ + static int s_var1; + static int s_var2=10; + + char *str="Hello"; + char *ptr; + + ptr = malloc(100); + + printf("[cmd args]: argv address: %p\n", argv); + printf("\n"); + + printf("[ Stack]: str address: %p\n", &str); + printf("[ Stack]: ptr address: %p\n", &ptr); + printf("\n"); + + printf("[ Heap ]: malloc address: %p\n", ptr); + printf("\n"); + + + printf("[ bss ]: s_var1 address: %p value: %d\n", &s_var1, g_var1); + printf("[ bss ]: g_var1 address: %p value: %d\n", &g_var1, g_var1); + + printf("[ data ]: g_var2 address: %p value: %d\n", &g_var2, g_var2); + printf("[ data ]: s_var2 address: %p value: %d\n", &s_var2, s_var2); + + printf("[rodata]: \"%s\" address: %p \n", str, str); + printf("\n"); + + printf("[ text ]: main() address: %p\n", main); + printf("\n"); + + + return 0; +} diff --git a/ch3_fork/popen.c b/ch3_fork/popen.c new file mode 100644 index 0000000..6a8e089 --- /dev/null +++ b/ch3_fork/popen.c @@ -0,0 +1,88 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <ctype.h> + +int get_ipaddr(char *interface, char *ipaddr, int ipaddr_size); + +int main(int argc, char **argv) +{ + char ipaddr[16]; + char *interface="eth0"; + + memset(ipaddr, 0, sizeof(ipaddr)); + + if( get_ipaddr(interface, ipaddr, sizeof(ipaddr)) < 0 ) + { + printf("ERROR: get IP address failure\n"); + return -1; + } + + printf("get network interface %s IP address [%s]\n", interface, ipaddr); + return 0; +} + +int get_ipaddr(char *interface, char *ipaddr, int ipaddr_size) +{ + char buf[1024]; + char *ptr; + char *ip_start; + char *ip_end; + FILE *fp; + int len; + int rv; + + if( !interface || !ipaddr || ipaddr_size<16 ) + { + printf("Invalid input arguments\n"); + return -1; + } + + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "ifconfig %s", interface); + if( NULL == (fp=popen(buf, "r")) ) + { + printf("popen() to excute command \"%s\" failure: %s\n", buf, strerror(errno)); + return -2; + } + + rv = -3; /* Set default return value to -3 means parser failure */ + + while( fgets(buf, sizeof(buf), fp) ) + { + if( strstr(buf, "netmask") ) + { + ptr=strstr(buf, "inet"); + if( !ptr ) + { + break; + } + ptr += strlen("inet"); + + while( isblank(*ptr) ) + ptr++; + + ip_start = ptr; + + while( !isblank(*ptr) ) + ptr++; + + ip_end = ptr; + memset(ipaddr, 0, sizeof(ipaddr)); + + len = ip_end-ip_start; + len = len>ipaddr_size ? ipaddr_size : len; + memcpy(ipaddr, ip_start, len); + + rv = 0; /* Parser IP address OK and set rv to 0 */ + + break; + } + } + + return rv; +} diff --git a/ch3_fork/socket_server.c b/ch3_fork/socket_server.c new file mode 100644 index 0000000..875386c --- /dev/null +++ b/ch3_fork/socket_server.c @@ -0,0 +1,162 @@ +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <stdlib.h> +#include <getopt.h> + +#define MSG_STR "Hello LingYun IoT Studio Client\n" + +void print_usage(char *progname) +{ + printf("%s usage: \n", progname); + printf("-p(--port): sepcify server listen port.\n"); + printf("-h(--Help): print this help information.\n"); + + return ; +} + +int main(int argc, char **argv) +{ + int sockfd = -1; + int rv = -1; + struct sockaddr_in servaddr; + struct sockaddr_in cliaddr; + socklen_t len; + int port = 0; + int clifd; + int ch; + int on = 1; + pid_t pid; + + struct option opts[] = { + {"port", required_argument, NULL, 'p'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + while( (ch=getopt_long(argc, argv, "p:h", opts, NULL)) != -1 ) + { + switch(ch) + { + case 'p': + port=atoi(optarg); + break; + + case 'h': + print_usage(argv[0]); + return 0; + } + + } + + if( !port ) + { + print_usage(argv[0]); + return 0; + } + + sockfd=socket(AF_INET, SOCK_STREAM, 0); + if(sockfd < 0) + { + printf("Create socket failure: %s\n", strerror(errno)); + return -1; + } + printf("Create socket[%d] successfully!\n", sockfd); + + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family=AF_INET; + servaddr.sin_port = htons(port); + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + //inet_aton("192.168.0.16", &servaddr.sin_addr); + + rv=bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); + if(rv < 0) + { + printf("Socket[%d] bind on port[%d] failure: %s\n", sockfd, port, strerror(errno)); + return -2; + } + + listen(sockfd, 13); + printf("Start to listen on port [%d]\n", port); + + while(1) + { + printf("Start accept new client incoming...\n"); + + clifd=accept(sockfd, (struct sockaddr *)&cliaddr, &len); + if(clifd < 0) + { + printf("Accept new client failure: %s\n", strerror(errno)); + continue; + } + + printf("Accept new client[%s:%d] successfully\n", + inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); + + pid = fork(); + if( pid < 0 ) + { + printf("fork() create child process failure: %s\n", strerror(errno)); + close(clifd); + continue; + } + else if( pid > 0 ) + { + /* Parent process close client fd and goes to accept new socket client again */ + close(clifd); + continue; + } + else if ( 0 == pid ) + { + char buf[1024]; + + /* Child process close the listen socket fd */ + close(sockfd); + + printf("Child process start to commuicate with socket client...\n"); + memset(buf, 0, sizeof(buf)); + rv=read(clifd, buf, sizeof(buf)); + if( rv < 0) + { + printf("Read data from client sockfd[%d] failure: %s\n", clifd, strerror(errno)); + close(clifd); + exit(0); + } + else if( rv == 0) + { + printf("Socket[%d] get disconnected\n", clifd); + close(clifd); + exit(0); + } + else if( rv > 0 ) + { + printf("Read %d bytes data from Server: %s\n", rv, buf); + } + + rv=write(clifd, MSG_STR, strlen(MSG_STR)); + if(rv < 0) + { + printf("Write to client by sockfd[%d] failure: %s\n", sockfd, strerror(errno)); + close(clifd); + exit(0); + } + + sleep(1); + + printf("close client socket[%d] and child process exit\n", clifd); + close(clifd); + exit(0); + } + } + + + close(sockfd); + + return 0; +} -- Gitblit v1.9.1