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;
实例:
#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)的更多相关文章
- linux 学习笔记 GNU工具链简介
我们通常无法直接通过Linux内核,而需要借助Linux内核之上的GUN工具链来进行 文件处理 文本操作 进程管理 等操作. GNU/Linux shell为用户提供了 启动程序 管理文件系统上的文件 ...
- GNU工具链学习笔记
GNU工具链学习笔记 1..so为动态链接库,.a为静态连接库.他们在Linux下按照ELF格式存储.ELF有四种文件类型.可重定位文件(Relocatable file,*.o,*.a),包含代码和 ...
- 使用GNU工具链进行嵌入式裸机开发
Embedded-Programming-with-the-GNU-Toolchain Vijay Kumar B. vijaykumar@bravegnu.org 翻译整理:thammer gith ...
- Linux C++程序进行性能分析工具gprof使用入门
性能分析工具 软件的性能是软件质量的重要考察点,不论是在线服务程序还是离线程序,甚至是终端应用,性能都是用户体验的关键.这里说的性能重大的范畴来讲包括了性能和稳定性两个方面,我们在做软件测试的时候也是 ...
- DIY FRDM-KL25Z开发环境 -- 基于GNU工具链
IDE大行其道的今天,一键make极大的便利了开发的同时,也每每让各种半路出家的猿们遇到工具链的问题感到束手无策(不就是说自己嘛?^_^!!!).也玩过不少板子了,始终没去深究工具链方面的问题,对于嵌 ...
- Linux下程序包管理工具RPM
实验环境: CentOS release 6.6 (Final) 一台 IP地址:172.16.249.230 RPM 是 Red Hat Package Manager 的缩写,本意是Red Ha ...
- RISC-V GNU 工具链:安装与使用
1. 安装Wmware和unbuntu,我安装的是Wmware workstation pro 12.1.1 build-3770994, unbuntu 是18.04.2 amd版本, ubuntu ...
- 练习--LINUX进程间通信之无名管道PIPE
IBM上放的这个系统不错,刚好可以系统回温一下LINUX的系统知识. http://www.ibm.com/developerworks/cn/linux/l-ipc/part1/ 感觉年纪大了,前几 ...
- linux后台程序开发常用工具
linux开发工具: 1.编辑工具:1)sourceInsight2)Notepad++3)UltraEdit4)Altova XMLSpy 2.linux服务器访问工具:1)FileZilla2)X ...
随机推荐
- WCF性能优势体现 【转】
WCF性能优势决定了其受欢迎程度,这些优势主要都体现在:统一性:互操作性:安全与可信赖:兼容性等方面. WCF是使用托管代码建立和运行面向服务(Service Oriented)应用程序的统一框架. ...
- visual studio 资源视图 空白 解决方案
visual studio 资源视图打开后显示空白的解决方案步骤: 在解决方案view下,右键点击工程 1 unload projects 完成第一步后仍然在解决方案view下,右键点击工程 2 re ...
- 向老项目JSP集成JSTL遇到的问题
today,I Failed to load or instantiate TagLibraryValidator class - JstlCoreTLV <%@ page contentTyp ...
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
- 洛谷1440 求m区间内的最小值
洛谷1440 求m区间内的最小值 本题地址:http://www.luogu.org/problem/show?pid=1440 题目描述 一个含有n项的数列(n<=2000000),求出每一项 ...
- vimrc语法
前言 工欲善其事,必先利其器.一个programmer必然要先有一个好的editor.vim就是一个十分强大的编辑器.它的强大之处,在于其个性化和可定制.学习vim,就像学习Linux,学习perl, ...
- datasorttable表格
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- JAVA从零单排之前因
本人,男,21岁,普通院校本科,计算机专业.大学之前对计算机编程没有一点涉及.大学学计算机专业也是个偶然.因为当初高考的成绩不好,结果都是我父亲帮我报的学校和专业. 上了大学之后,大一都是在新奇中度过 ...
- mysql查询随机几条数据(速度快)
MySql查询随机几条数据 想到了 Max RAND 这几个函数 用以下2种办法都可以实现查询. 速度还行. 几十万数据左右, 没有什么问题. SELECT * FROM `news` WHERE i ...
- ContentProvider与ContentResolver使用
例如以下内容为从网络转载: 使用ContentProvider共享数据: 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就能够向其它应用共享其数据.虽然使用其它方 ...