zoukankan      html  css  js  c++  java
  • Linux简单程序实例(GNU工具链,进程,线程,无名管道pipe,基于fd的文件操作,信号,scoket)

    一, GNU工具链简介:

            (1)编译代码步骤:

                  预处理 -> 编译 -> 汇编 -> 链接;

                  

                  预处理:去掉注释,进行宏替换,头文件包含等工作;

                  gcc -E test.c -o test.i

                  编译:   不同平台使用汇编语言不同,汇编将高级语言编译成汇编语言;

                  gcc -S test.c -o test.s

                  汇编:   将汇编语言翻译成二进制代码;

                  gcc -c test.c -o test.o

                  链接:   包含各函数库的入口,得到可执行文件;

                  gcc -o test test.c

           (2)gcc编译:

                  .c文件编译:gcc -o DESFILE SRCFILE ,将源c文件SRCTILE编译为可执行文件DESFILE ;

                                  gcc -o DESFILE SRCFILE ,加上-g选项,生成的可执行文件DESFILE可进行调试;

           (2)gdb调试:

                  调试前提:gcc编译时加入-g参数;

                  调试选项:gdb DESFILE 进入调试,

                               l 列出代码信息,后面可带整数参数;

                               b 设断点,后面跟要设断点的函数名或者行数;

                               r 运行;

                               n 下一步;

                               c 继续;

                               q 退出,退出调试;

    二,Linux下简单编程实例:

            (1)进程创建:

                   函数说明:

                  #include <sys/types.h>

                  #include <unistd.h>

                  pid_t fork();

                  调用fork()创建进程,若创建成功,父进程返回子进程ID(>0),子进程返回0,出错返回-1;

                  

                  实例:

                 

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <unistd.h>
     4 
     5 int main(void)
     6 {
     7        pid_t child_pid;
     8        printf("the main program process ID is:%d",(int)getpid);
     9        child_pid = fork();
    10        if(child_pid >0)
    11        {
    12              printf("This is parent process:%d
    ",(int)getpid);
    13         }
    14         else if(pid == 0)
    15         {
    16              printf("This is child process:%d
    ",(int)getpid);
    17          }
    18          else
    19          {
    20              printf("fork() occurr erro!
    ");
    21          }
    22          return 0;
    23 }
    View Code

                  

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <unistd.h>
     4 
     5 int spawn(char* progam,char** arg_list)
     6 {
     7         pid_t child_pid;
     8         child_pid = fork();
     9         if(child_pid!=0)
    10         {
    11                 return child_pid;
    12         }
    13         else
    14         {
    15                 execvp(program,arg_list);
    16                 fprintf(stderr,"Erro occured!
    ");
    17                 abort();
    18          }
    19          return 0;
    20 }
    21 
    22 int main(void)
    23 {
    24          char* arg_list[] = {"ls","-l","/",NULL};
    25          spawn("ls",arg_list);
    26          return 0;
    27 }
    View Code

             (2)线程创建:

                    函数说明:

                    int pthread_create(pthread_t *thread,const pthread_attr_t *attr,

                                                         void *(start_routine)(void *),void *arg);

                    第一个参数为线程ID;

                    第二个参数为线程属性,可默认为NULL;

                    第三个参数为线程执行的函数;

                    第四个为函数的参数;

               实例:

               线程创建:

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <pthread.h>
     4 
     5 void* print_x(void* unused)
     6 {
     7        while(1)
     8        {
     9             printf("x");
    10         }
    11         return NULL;
    12 }
    13 
    14 int main(void)
    15 {
    16         pthread_t thread_id;
    17         pthread_create(&thread_id,NULL,&print_x,NULL);
    18         while(1)
    19         {
    20              printf("s");
    21         }
    22         return 0;
    23 }
    View Code

              (3)信号:

                      signal:软件中断,传递给进程的异步消息;

                      当进程收到信号后,将立即对信号进行处理;

                      信号可以在任何代码位置中断;

                      

               实例:

               

     1 #include <stdio.h>
     2 #include <signal.h>
     3 #include <sys/types.h>
     4 #include <unistd.h>
     5 
     6 void sig_usr(int signo)
     7 {
     8        printf("Receive signal !
    ");
     9 }
    10 
    11 int main(void)
    12 {
    13        printf("%d
    ",(int)getpid());
    14        if(signal(SIGUSR1,sig_usr)==SIG_ERR)
    15        {
    16              printf("Can't catch signal");
    17        }
    18        for(;;)
    19        {
    20              pause();
    21        }
    22        return 0;
    23 }
    View Code

                (4)线程,信号量

                       

                 实例:

                 

     1 void* thread_fun(void* arg)
     2 {
     3        while(1)
     4        {
     5                 pthread_mutex_lock(&thread_flag_mutex);
     6                 while(!thread_flag)
     7                 {
     8                                  thread_cond_wait(&thread_flag_cv,&thread_flag_mutex);
     9                 }
    10                 pthread_mutex_unlock();
    11                 do_work();
    12        }
    13        return NULL;
    14 }
    15 
    16 void set_thread_flag(int flag_vlaue)
    17 {
    18        pthread_mutex_lock(&thread_flag_mutex);
    19        thread_flag_mutex = flag_vlaue;
    20        pthread_cond_signal(&thread_flag_cv);
    21        pthread_mutex_unlock(&thread_flag_mutex);
    22 }
    View Code

                

                (5)无名管道pipe:

                      函数原型: int pipe(int fd[2]);

                     生成两个文件描述符,一个用于读f[0],一个用于写f[1];

                     无名管道的使用条件:父子进程;

                 实例:

                    

                 

     1 #include <unistd>
     2 
     3 int main(void)
     4 {
     5       int fd[2];
     6       char buffer[80];
     7       pipe(fd);
     8       if(fork()>0)
     9       {
    10             char s[] = "Hello!
    ";
    11             write(fd[1],s,sizeof(s));
    12       }
    13       else
    14       {
    15            read(fd[1],buffer,80);
    16            printf("buffer: %s",buffer);
    17       }
    18       return 0;
    19 }
    View Code

                 (6)基于文件描述符的文件简单操作:

                  文件打开与关闭函数:

                  #include <sys/types.h>

                  #include <sys/stat.h>

                  #include <fcntl.h>

                  int open(const char *pathname,int flags);

                  int open(const char *pathname,int flags,mode_t mode);

                  int close(int fd);

                  flags类型:flags决定文件的打开方式,有以下常用类型:

                                 O_RDONLY:只读;      O_RDWR:读写;

                                 O_WRONLY:只写;      O_CREAT:若文件不存在则创建;     

                  文件读写函数:

                  #include <unistd.h>

                  ssize_t read(int fd,void *buf,size_t count);

                  ssize_t write(int fdvoid *buf,size_t count);

                  

                  文件的定位:

                  #include <sys/types.h>

                  #include <unistd.h>

                  off_t lseek(int fd,off_t offset,int whence);

                  fd:文件注释符;

                  offset:偏移量;

                  whence:取值范围:SEEK_SET(将文件位移量设置为据文件开始出offset字节);

                                           SEEK_CUR(将文件位移量设置为当前值+offset字节);

                                           SEEK_END(将文件位移量设置为文件长度+offset字节);

                 

                   

                   实例:

                   

     1 #include <unistd.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <fcntl.h>
     5 
     6 int main(void)
     7 {
     8       char s[] = "Linux c program!
    "
     9       char buffer[80];
    10       int fd,count;
    11       fd = open("./test.txt",O_WRONLY|O_CREAT);
    12       write(fd,s,sizeof(s));
    13       close(fd);
    14       fd = open("./test.txt",O_RDONLY);
    15       count = read(fd,buffer,80);
    16       close(fd);
    17       printf("buffer:%s",buffer);
    18       return 0;
    19 }
    View Code

                  (7)socket客户端与服务器端:

                    基于TCP的socket通信流程:

                               

                    socket套接字基础:

                                   IPV4套接字:

                                   #include <netinet/in.h>

                                   struct sockaddr_in

                                   {

                                            unsigned short        sin_len;        //IPV4 地址长度

                                            sa_family_t             sin_family;   //通信地址类型,AF_INET对应IPV4, AF_INET6对应IPV6

                                            unsigned short int    sin_port;     //16位端口号,以网络字节序存储

                                            struct in_addr          sin_addr;    //将要访问的IP地址, 其中struct in_addr{uint32_t s_addr;}以网络字节顺序

                                            unsigned char          sin_zero[8];//未使用的字段,填充为0

                                     }

                               

                                      struct hostent结构体定义:

                                      struct hostent

                                      {

                                             char   *h_name;         //主机正式名称

                                             char   **h_aliases;      //主机别名

                                             int     h_addrtype;      //主机地址类型,IPV4为AF_INET

                                             int     h_length;          //地址长度,IPV4为4字节,32位

                                             char   **h_addr_list;   //主机IP地址列表

                                       };

                                       函数:

                                       #include <netdb.h>

                                       struct hostent *gethostbyname(const char *hostname);                      //实现域名或主机名到IP地址的转换

                                       struct hostent *gethostbyaddr(const char *addr,size_t len,int family);  //实现IP地址到域名或主机名的转换

                    客户端:

                    主要函数:

                    socket():建立套接字,设定远程IP和端口;

                    connect():连接远程计算机指定端口;

                    read()或recv(),读取客户端发来的数据;

                    write()或send()发送数据;

                        

              
     1 #include <sys/types.h>
     2 #include <sys/socket.h>
     3 #include <stdio.h>
     4 #include <netinet/in.h>
     5 #include <arpa/inet.h>
     6 #include <unistd.h>
     7 #include <string.h>
     8 #include <stdlib.h>
     9 #include <fcntl.h>
    10 #include <sys/shm.h>
    11 
    12 #define MYPORT  8887
    13 #define BUFFER_SIZE 1024
    14 
    15 int main()
    16 {
    17     ///定义sockfd
    18     int sock_cli = socket(AF_INET,SOCK_STREAM, 0);
    19 
    20     ///定义sockaddr_in
    21     struct sockaddr_in servaddr;
    22     memset(&servaddr, 0, sizeof(servaddr));
    23     servaddr.sin_family = AF_INET;
    24     servaddr.sin_port = htons(MYPORT);  ///服务器端口
    25     servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");  ///服务器ip
    26 
    27     ///连接服务器,成功返回0,错误返回-1
    28     if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
    29     {
    30         perror("connect");
    31         exit(1);
    32     }
    33 
    34     char sendbuf[BUFFER_SIZE];
    35     char recvbuf[BUFFER_SIZE];
    36     while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
    37     {
    38         send(sock_cli, sendbuf, strlen(sendbuf),0); ///发送
    39         if(strcmp(sendbuf,"exit
    ")==0)
    40             break;
    41         recv(sock_cli, recvbuf, sizeof(recvbuf),0); ///接收
    42         fputs(recvbuf, stdout);
    43 
    44         memset(sendbuf, 0, sizeof(sendbuf));
    45         memset(recvbuf, 0, sizeof(recvbuf));
    46     }
    47 
    48     close(sock_cli);
    49     return 0;
    50 }
    View Code

                    服务器端:

                    主要函数:

                    socke():建立套接字,用这个套接字完成通讯监听,数据收发;

                    bind(): 绑定一个端口号和一个IP,使套接字与之关联;

                    listen():使服务器该端口和IP处于监听状态,等待连接请求;

                    accept():接收远程计算机的连接请求,建立服务器与客户端之间的连接;

                    read()或recv(),读取客户端发来的数据;

                    write()或send()发送数据;

              
     1 #include <sys/types.h>
     2 #include <sys/socket.h>
     3 #include <stdio.h>
     4 #include <netinet/in.h>
     5 #include <arpa/inet.h>
     6 #include <unistd.h>
     7 #include <string.h>
     8 #include <stdlib.h>
     9 #include <fcntl.h>
    10 #include <sys/shm.h>
    11 
    12 #define MYPORT  8887
    13 #define QUEUE   20
    14 #define BUFFER_SIZE 1024
    15 
    16 int main()
    17 {
    18     ///定义sockfd
    19     int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);
    20 
    21     ///定义sockaddr_in
    22     struct sockaddr_in server_sockaddr;
    23     server_sockaddr.sin_family = AF_INET;
    24     server_sockaddr.sin_port = htons(MYPORT);
    25     server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    26 
    27     ///bind,成功返回0,出错返回-1
    28     if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)
    29     {
    30         perror("bind");
    31         exit(1);
    32     }
    33 
    34     ///listen,成功返回0,出错返回-1
    35     if(listen(server_sockfd,QUEUE) == -1)
    36     {
    37         perror("listen");
    38         exit(1);
    39     }
    40 
    41     ///客户端套接字
    42     char buffer[BUFFER_SIZE];
    43     struct sockaddr_in client_addr;
    44     socklen_t length = sizeof(client_addr);
    45 
    46     ///成功返回非负描述字,出错返回-1
    47     int conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length);
    48     if(conn<0)
    49     {
    50         perror("connect");
    51         exit(1);
    52     }
    53 
    54     while(1)
    55     {
    56         memset(buffer,0,sizeof(buffer));
    57         int len = recv(conn, buffer, sizeof(buffer),0);
    58         if(strcmp(buffer,"exit
    ")==0)
    59             break;
    60         fputs(buffer, stdout);
    61         send(conn, buffer, len, 0);
    62     }
    63     close(conn);
    64     close(server_sockfd);
    65     return 0;
    66 }
    View Code

                     

  • 相关阅读:
    关于MySQL INT类型长度的疑惑
    uwp 的锁屏功能
    QT5 动态链接库的创建和使用
    Qt 自定义事件的实现
    学习k8s本地虚拟机安装minikube
    建议收藏!细说HashMap实现,Hash冲突模拟思路讲解。
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees(dp)
    574 React系列(一)
    如何在Win7电脑上增加新磁盘分区?
  • 原文地址:https://www.cnblogs.com/weiyikang/p/5011715.html
Copyright © 2011-2022 走看看