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

                 

原文地址:https://www.cnblogs.com/weiyikang/p/5011715.html