一, 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;

实例:

 #include <stdio.h>
#include <sys/types.h>
#include <unistd.h> int main(void)
{
pid_t child_pid;
printf("the main program process ID is:%d",(int)getpid);
child_pid = fork();
if(child_pid >)
{
printf("This is parent process:%d\n",(int)getpid);
}
else if(pid == )
{
printf("This is child process:%d\n",(int)getpid);
}
else
{
printf("fork() occurr erro!\n");
}
return ;
}
 #include <stdio.h>
#include <sys/types.h>
#include <unistd.h> int spawn(char* progam,char** arg_list)
{
pid_t child_pid;
child_pid = fork();
if(child_pid!=)
{
return child_pid;
}
else
{
execvp(program,arg_list);
fprintf(stderr,"Erro occured!\n");
abort();
}
return ;
} int main(void)
{
char* arg_list[] = {"ls","-l","/",NULL};
spawn("ls",arg_list);
return ;
}

(2)线程创建:

函数说明:

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

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

第一个参数为线程ID;

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

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

第四个为函数的参数;

实例:

线程创建:

 #include <stdio.h>
#include <sys/types.h>
#include <pthread.h> void* print_x(void* unused)
{
while()
{
printf("x");
}
return NULL;
} int main(void)
{
pthread_t thread_id;
pthread_create(&thread_id,NULL,&print_x,NULL);
while()
{
printf("s");
}
return ;
}

(3)信号:

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

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

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

实例:

 #include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h> void sig_usr(int signo)
{
printf("Receive signal !\n");
} int main(void)
{
printf("%d\n",(int)getpid());
if(signal(SIGUSR1,sig_usr)==SIG_ERR)
{
printf("Can't catch signal");
}
for(;;)
{
pause();
}
return ;
}

(4)线程,信号量

实例:

 void* thread_fun(void* arg)
{
while()
{
pthread_mutex_lock(&thread_flag_mutex);
while(!thread_flag)
{
thread_cond_wait(&thread_flag_cv,&thread_flag_mutex);
}
pthread_mutex_unlock();
do_work();
}
return NULL;
} void set_thread_flag(int flag_vlaue)
{
pthread_mutex_lock(&thread_flag_mutex);
thread_flag_mutex = flag_vlaue;
pthread_cond_signal(&thread_flag_cv);
pthread_mutex_unlock(&thread_flag_mutex);
}

(5)无名管道pipe:

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

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

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

实例:

 #include <unistd>

 int main(void)
{
int fd[];
char buffer[];
pipe(fd);
if(fork()>)
{
char s[] = "Hello!\n";
write(fd[],s,sizeof(s));
}
else
{
read(fd[],buffer,);
printf("buffer: %s",buffer);
}
return ;
}

(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字节);

实例:

 #include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> int main(void)
{
char s[] = "Linux c program!\n"
char buffer[];
int fd,count;
fd = open("./test.txt",O_WRONLY|O_CREAT);
write(fd,s,sizeof(s));
close(fd);
fd = open("./test.txt",O_RDONLY);
count = read(fd,buffer,);
close(fd);
printf("buffer:%s",buffer);
return ;
}

(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()发送数据;

 #include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h> #define MYPORT 8887
#define BUFFER_SIZE 1024 int main()
{
///定义sockfd
int sock_cli = socket(AF_INET,SOCK_STREAM, ); ///定义sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MYPORT); ///服务器端口
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ///服务器ip ///连接服务器,成功返回0,错误返回-1
if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < )
{
perror("connect");
exit();
} char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
send(sock_cli, sendbuf, strlen(sendbuf),); ///发送
if(strcmp(sendbuf,"exit\n")==)
break;
recv(sock_cli, recvbuf, sizeof(recvbuf),); ///接收
fputs(recvbuf, stdout); memset(sendbuf, , sizeof(sendbuf));
memset(recvbuf, , sizeof(recvbuf));
} close(sock_cli);
return ;
}

服务器端:

主要函数:

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

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

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

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

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

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

 #include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h> #define MYPORT 8887
#define QUEUE 20
#define BUFFER_SIZE 1024 int main()
{
///定义sockfd
int server_sockfd = socket(AF_INET,SOCK_STREAM, ); ///定义sockaddr_in
struct sockaddr_in server_sockaddr;
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(MYPORT);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); ///bind,成功返回0,出错返回-1
if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-)
{
perror("bind");
exit();
} ///listen,成功返回0,出错返回-1
if(listen(server_sockfd,QUEUE) == -)
{
perror("listen");
exit();
} ///客户端套接字
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr); ///成功返回非负描述字,出错返回-1
int conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length);
if(conn<)
{
perror("connect");
exit();
} while()
{
memset(buffer,,sizeof(buffer));
int len = recv(conn, buffer, sizeof(buffer),);
if(strcmp(buffer,"exit\n")==)
break;
fputs(buffer, stdout);
send(conn, buffer, len, );
}
close(conn);
close(server_sockfd);
return ;
}

Linux简单程序实例(GNU工具链,进程,线程,无名管道pipe,基于fd的文件操作,信号,scoket)的更多相关文章

  1. linux 学习笔记 GNU工具链简介

    我们通常无法直接通过Linux内核,而需要借助Linux内核之上的GUN工具链来进行 文件处理 文本操作 进程管理 等操作. GNU/Linux shell为用户提供了 启动程序 管理文件系统上的文件 ...

  2. GNU工具链学习笔记

    GNU工具链学习笔记 1..so为动态链接库,.a为静态连接库.他们在Linux下按照ELF格式存储.ELF有四种文件类型.可重定位文件(Relocatable file,*.o,*.a),包含代码和 ...

  3. 使用GNU工具链进行嵌入式裸机开发

    Embedded-Programming-with-the-GNU-Toolchain Vijay Kumar B. vijaykumar@bravegnu.org 翻译整理:thammer gith ...

  4. Linux C++程序进行性能分析工具gprof使用入门

    性能分析工具 软件的性能是软件质量的重要考察点,不论是在线服务程序还是离线程序,甚至是终端应用,性能都是用户体验的关键.这里说的性能重大的范畴来讲包括了性能和稳定性两个方面,我们在做软件测试的时候也是 ...

  5. DIY FRDM-KL25Z开发环境 -- 基于GNU工具链

    IDE大行其道的今天,一键make极大的便利了开发的同时,也每每让各种半路出家的猿们遇到工具链的问题感到束手无策(不就是说自己嘛?^_^!!!).也玩过不少板子了,始终没去深究工具链方面的问题,对于嵌 ...

  6. Linux下程序包管理工具RPM

    实验环境: CentOS release 6.6 (Final)  一台 IP地址:172.16.249.230 RPM 是 Red Hat Package Manager 的缩写,本意是Red Ha ...

  7. RISC-V GNU 工具链:安装与使用

    1. 安装Wmware和unbuntu,我安装的是Wmware workstation pro 12.1.1 build-3770994, unbuntu 是18.04.2 amd版本, ubuntu ...

  8. 练习--LINUX进程间通信之无名管道PIPE

    IBM上放的这个系统不错,刚好可以系统回温一下LINUX的系统知识. http://www.ibm.com/developerworks/cn/linux/l-ipc/part1/ 感觉年纪大了,前几 ...

  9. linux后台程序开发常用工具

    linux开发工具: 1.编辑工具:1)sourceInsight2)Notepad++3)UltraEdit4)Altova XMLSpy 2.linux服务器访问工具:1)FileZilla2)X ...

随机推荐

  1. 再也不用担心ie下console.log报错了。。。

    习惯了在ff或者chrome下暴力调试的你会不会忘记注释掉而在ie下报错呢,那么可以加这个代码: if (typeof console == "undefined") { this ...

  2. mysql忘记帐号密码 解决办法

    首先关闭mysql 使用命令行启动mysql(一般要找到mysql.ini文件) 在windows上mysql.ini文件可以通过查看当前mysql进程参数查看到,具体方法点此 在启动mysql命令行 ...

  3. 稀疏矩阵coo_matrix的乘法

    稀疏矩阵的乘法在做基于n-gram的分类的时候还是相当有用的,但是由于网上资料太少,所以折腾了几天才算折腾出来. 首先scipy包里常见的稀疏矩阵有三种形式, coo_matrix, csr_matr ...

  4. usaco 打扫食槽

    Description 从前奶牛是不挑食的,但现在世道变了,她们变得非常挑剔.牧场里有N头奶牛,约翰 要向她们提供M种食物,第i头奶牛只会吃Pi号食物. 约翰每天都要打扫食槽,这件事非常累.奶牛沿着食 ...

  5. In Java, what is the default location for newly created files?

    If the current directory of the application. If e.g. you create a File by using new FileOutputStream ...

  6. hdoj 1789 Doing Homework again

    Doing Homework again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  7. linux下利用openssl来实现证书的颁发(详细步骤)

    1.首先需要安装openssl,一个开源的实现加解密和证书的专业系统.在centos下可以利用yum安装. 2.openssl的配置文件是openssl.cnf,我们一般就是用默认配置就可以.如果证书 ...

  8. 批处理(.bat)中使用相对路径

    批处理中使用相对路径,只需要用cd /d %~dp0代替绝对路径就可以了. ->cd /d ->%~dp0 %0为当前批处理文件 %~d0 是指批处理所在的盘符 %~dp0 是指批处理所在 ...

  9. 推荐一个markdown编辑器-Haroopad

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:推荐一个markdown编辑器-Haroopad.

  10. 使用CLRMD编写一个自己的C#调试器

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:使用CLRMD编写一个自己的C#调试器.