- 博客(76)
- 资源 (2)
- 收藏
- 关注
原创 Linux系统编程——线程(一)进程和线程的区别、线程的优点、以及线程开发的API
进程和线程进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位。在面向线程设计的系统中,进程本身不是基本运行单位,而是线程的容器。程序本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。线程包含了表示进程内执行环境必须的信息,其中包括进程中表示线程的线程ID、一
2021-06-13 01:58:08
252
原创 Linux系统编程——进程间的通信(六)信号量
信号量信号量(Semaphore),是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量。它是一个计数器。信号量用于实现进程或者线程间的互斥与同步,而不是用于存储进程间通信数据。特点(1)信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。(2)信号量基于操作系统的P
2021-06-12 20:31:37
410
原创 C语言不使用中间变量交换两个变量的数据
在一般情况下,我们交换两个变量的数据都需要第三个变量作为中间变量,如下#include <stdio.h>int main(){ int a = 10; int b = 20; int c; printf("交换前a = %d,b = %d\n",a,b); c = b; b = a; a = c; printf("交换后a = %d,b = %d\n",a,b); return 0;}那么怎样才能不使用第三个
2021-06-12 11:01:17
2424
原创 Linux系统编程——进程间的通信(五)信号
对于 Linux来说,实际信号是软中断,许多重要的程序都需要处理信号。信号为 Linux 提供了一种处理异步事件的方法。比如,终端用户输入了 ctrl+c 来中断程序,会通过信号机制停止一个程序 。信号概述...
2021-06-12 02:34:36
828
原创 Linux系统编程——进程间的通信(四)共享内存
什么是共享内存和共享内存的特点?所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。原理进程A将信息放入共享内存中进程B从共享内存中读取编程步骤1、创建或者打开共享内存2、进程A连接(映射)共享内存,写入数据3、进程A断开4、进程B连接(映射)共享内存,读取数据5、进程B断开6、释放共享内存常用API1 #include <sys/shm.h>
2021-05-12 23:10:11
316
2
原创 Linux系统编程——进程间的通信(三)消息队列原理以及用法
消息队列是消息的链接表,存放在内核中,一个消息队列由一个标识符(队列ID)来标识。特点:1、消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级2、消息队列独立于发送与接收进程,进程终止时,消息队列中的内容不会被删除3、消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按照消息的类型读取原理消息队列常用API头文件#include <sys/types.h>#include <sys/ipc.h>#include <sys/
2021-05-11 00:07:21
8747
原创 Linux系统编程——进程间的通信(二)无名管道和命名管道
一、无名管道管道通常是指无名管道,(因为没有文件名,所以叫无名管道)是 UNIX 系统IPC最古老的形式。特点:1、它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。2、它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。3、它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。4、管道中的数据被读走了,管道中就没有数据了。原理当建立一个管道时,由参数fd返
2021-05-09 01:18:10
917
原创 Linux系统编程——进程间的通信(一)进程通信的概述
一、最基本的进程通信1、创建子进程,当子进程退出时,父进程收集子进程的信息2、使用exec族函数不管是用fork函数创建子进程还是用exec族函数,这些都是不全的进程通信二、真正意义上的进程通信——IPC两个进程间进行通信IPC的方式通常有管道(无名管道和命名管道),消息队列,信号量,共享储存,Socket、Streams等,其中Socket、Streams支持两台PC机上的两个进程。单机通信:如果是在一台机器上,则为单机通信 ,如半双工管道,全双工管道,消息队列,信号量,共享内存多机通
2021-05-08 21:29:10
244
原创 Linux系统编程——进程(六)system函数和popen函数
一、system函数头文件#include <stdlib.h>函数原型int system(const char *command);函数说明system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。返回值如果system()在调用/bin/sh时失败则返回1
2021-05-08 13:19:06
337
原创 Linux系统编程——进程(五)exec族函数,以及exec族函数和fork函数配合使用
exec族函数fork函数创建一个子进程的目的?1、一个父进程希望复制自己,使父,子进程同时执行不同的代码段,这在网络服务进程中是常见的——父进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务器请求到达。2、一个进程要执行一个不同的程序,这对shell是常见的情况,在这种情况下,子进程从fork返回后立即调用exec。exec族函数作用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时
2021-05-08 01:59:15
1095
原创 Linux系统编程——进程(四)进程的退出,子进程退出的信息收集,以及僵尸进程和孤儿进程
1、进程退出退出方式有两种:正常退出,异常退出正常退出有5种:1、Main函数调用return2、进程调用exit(),标准C库3、进程调用_exit()或者_Exit(),属于系统调用和线程有关的4、进程最后一个线程返回5、最后一个线程调用pthread_exit异常退出有三种:1、调用abort2、当进程收到某些信号时,如Ctrl + C3、最后一个线程对取消(cancellation),请求作出响应不管进程如何终止,最后都会执行内核中的同一段代码。这段代码为相应进程关闭所有打
2021-05-06 21:14:27
738
原创 Linux系统编程——进程(三)fork函数和vfork函数的区别
1、vfork函数直接使用父进程的存储空间,不拷贝2、vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行用fork函数创建进程#include <sys/types.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>int main(){ int data = 3; pid_t pid; pid = fork(); if(pid
2021-05-06 12:38:02
308
原创 Linux系统编程——进程(二)创建进程函数(fork) 父进程给子进程拷贝了什么内容 以及 fork为什么要创建子进程
一、fork函数头文件#include <unistd.h>函数原型pid_t fork(void);如#include <sys/types.h>#include <unistd.h>#include <stdio.h>int main(){ pid_t pid; pid = getpid(); //等于父进程pid值 fork(); //创建进程 printf("my pid is %d %
2021-05-06 01:33:00
909
原创 Linux系统编程——进程(一)关于进程的一些问题
一、什么是程序,什么是进程,有什么区别?程序:程序是静态的概念,是存放在磁盘中的可执行文件,如gcc data.c -o Pro,磁盘中生成一个Pro文件,叫做程序进程:进程是程序的一次运行活动,也就是程序运行起来了,在系统中又多了一个进程二、如何查看系统中有哪些进程?1: PS指令ps -aux :显示全部进程grep(文件查找) :显示部分进程使用方法ps -aux | grep init //显示关于init的进程2、使用top指令查看,类似于Windows的任务管理器,(可以
2021-05-05 19:25:29
239
原创 Linux系统编程——文件编程(八)用C语言标准库函数操作文件
1、fopen和fclosefopen是C的标准库函数,用来打开文件open和fopen1、open是Unix系统调用函数(包括Linux),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核API,返回的是一个指向文件结构的指针2、移植性“fopen”是C标准函数,因此具有很好的移植性,而“open”是Unix,Linux系统调用,移植性有限,3、范围open返回的是文件描述符,而
2021-05-05 11:47:09
491
原创 Linux系统编程——文件编程(七)向文件里面写入整数 结构体以及结构体数组
read和write函数原型为ssize_t read(int fd, void *buf, size_t count);ssize_t write(int fd, const void *buf, size_t count);一般对buf的操作都是写入或者读出字符串,由函数原型可以看出buf是一个无类型的指针,指针又是存放地址的,所以buf可以是一个变量的的地址1、向文件写入整数#include <sys/types.h>#include <sys/stat.h>#
2021-05-04 23:47:31
664
原创 Linux系统编程——文件编程(六)修改配置文件
修改配置文件主要运用了对文件的打开和读写的API,同时还用到了一个字符串查找函数(strstr)strstr函数头文件#include <string.h>函数原型char *strstr(const char *haystack, const char *needle);haystack:表示被查找的目标范围needle:表示要查找的对象返回值当在haystack中查找到字符串needle时,函数返回needle在haystack中第一次出现的首地址对于strlen函数
2021-05-04 18:15:08
251
原创 Linux系统编程——文件编程(五)自己实现CP指令
cp指令用于复制文件或目录,如同时指定两个以上的文件或目录,且最后的目的地是一个已经存在的目录,则它会把前面指定的所有文件或目录复制到此目录中。main的参数int main(void){/*代码*/}//整数类型主函数(无类型)int main(int argc,char **argv)//整数类型主函数(整数类型 统计参数个数,字符类型*数组指针至字符[])其中char **argv可以写成char argv[],两者等价argc:传入参数的个数argv:输入参数字符串,argv[0]为
2021-05-04 13:23:01
391
原创 Linux系统编程——文件编程(一)文件的创建 打开 关闭
1、创建(creat)创建文件可以用creat函数,也可以用和open函数进行创建。首先来看一下 creat 函数creat函数的头文件为#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>creat函数原型为 int creat(const char *pathname, mode_t mode)pathname:指向文件路径的指针,要创建的文件名mode:创建的文件模式,系
2021-05-03 20:36:48
607
原创 Linux系统编程——文件编程(二)文件描述符 文件编程的步骤 静态文件和动态文件
文件描述符:1、对内核而言,是通过文件描述符(file descriptor)来访问文件的。文件描述符是非负整数。打开现存文件或新建文件时,内核向进程返回一个文件描述符。当读写文件时,用open和creat函数返回的文件描述符标识该文件,将其作为参数传递给read和write函数。一般UNIX shell使用文件描述符 0 与进程的标准输入相结合,文件描述符1与标准输出相结合,文件描述符2与标准错误输出相结合,用STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO 这几个宏代
2021-05-03 20:34:55
215
原创 Linux系统编程——文件编程(三)文件的读出和写入
1、写入(write)头文件#include <unistd.h>函数原型ssize_t write(int fd, const void *buf, size_t count);参数:int fd :文件描述符const void *buf :字节缓冲区,buf为要写入的字符串,(buf为void的指针)size_t count:文件描述符写入字符串的大小write:在缓冲区buf中取count个字节写入到文件描述符fd指向的文件里面返回值写入成功:返回一个整型数,
2021-05-03 20:32:04
1018
原创 Linux系统编程——文件编程(四)光标移动(lseek)
lseek是一个用于改变读写一个文件时读写指针位置的一个系统函数每个打开的文件都有一个与其相关联的“当前文件偏移量”,它通常是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读写的字节数。头文件 #include <sys/types.h> #include <unistd.h>函数原型 off_t lseek(int fd, off_t offset, int whence)
2021-05-03 20:27:56
1037
原创 typedef关键字
**typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。使用typedef目的一般有两个,一个是给变量一个容易记并且意义明确的新名字,另一个是简化一些比较复杂的类声明。在单片机开发中需要配置一些寄存器,(8位、16位、32位),在这里typedef可以简化名字。比如typedef unsigned char u_int8; //8位无符号数typedef unsigned short int
2021-04-05 12:40:20
742
原创 计算结构体的大小
结构体用来保存不用类型的数据非常方便,但是计算结构体的大小并不是将变量所占的字节数相加,而是按照一定的对齐规则进行计算结构体的大小的。由于地址对齐的原因,结构体大小的计算必须满足两条原则:**一、结构体每一个成员相对于结构体首地址的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)**二、结构体的总大小必须是所有成员大小的整数倍(数组成员除外,结构体成员除外)下面通过代码来验证1、一般的结构体#include<stdio.h>#include<stdlib.h>
2021-04-05 01:13:10
317
原创 结构体指针、函数封装、字符串的结合
所谓结构体指针就是指向结构体变量的指针,一个结构体变量的起始地址就是这个结构体变量的指针,如果把一个结构体变量的起始地址存放在一个指针变量中,那么这个指针变量就指向该结构体变量。struct Student* pstu就定义了一个结构体指针,和整型的指针变量都差不多,pstu为结构体指针变量,用来存放结构体地址的变量,需要注意的是结构体指针是用“->”运算符来访问结构体中的成员,普通结构体变量访问成员是用“.”来访问。结构体指针的具体用法如下代码:#include<stdio.h>
2021-04-04 18:34:00
301
原创 结构体数组
一个结构体变量中可以存放一组有关联的数据,(如一个学生的名字,成绩),那如果有10个学生该怎么办呢?显然就要用数组,因为数组是存放同一类型的数据,这里的数组类型为结构体,所以称为结构体数组。结构体数组和整型数组都差不多,不同的地方就在于每个数组元素都是一个结构体类型的数据,它们都有各自的成员项。下面用一段代码来说明结构体数组的定义和引用:#include <stdio.h>#include <string.h>#include<stdlib.h>struct
2021-04-04 17:50:18
5401
原创 结构体的定义
1、结构体的定义在前面程序中,所用到的变量大多数都是相互独立的,没有内在联系,比如 int a; char c;都是相互独立的,但是有些情况需要把一些变量组合一起,比如,一个学生的名字,成绩,分数,学号等,都是不一样的数据类型,但是属于一个学生,如果定义了这些变量,他们也是相互独立的,不能反映这些变量的内在联系,有时候希望把这些属于一个人的数据组成一个组合数据。数组也可以同时存放一组数据,那为什么数组不能存放这些数据呢?因为数组只能存放同一类型的数据,不能存放不同内型的数据,比如不能同时存放一个人的名字
2021-04-04 17:19:41
3593
原创 自己封装字符串函数
1、putsvoid myPuts(char* p){ if(*p != '\0'){ printf("%s",p); } putchar('\n');}void myPuts(char* p){ while(*p != '\0'){ putchar(*p++); } putchar('\n');}2、getsint myGets(char* p){ int cnt = 0; //用来计数输
2021-04-03 16:43:32
269
原创 字符串操作常用函数
字符串常用函数有如下puts() //输出字符串gets() //获取字符串strlen() //计算字符串长度memset() //初始化strcpy() strncpy() //字符串的拷贝strcat() //字符串的拼接strcmp() //字符串的比较strchr() //字符串的查找strstr() strtok() //字符串分割strlwr() //字符串转为小写strupr() //字符串
2021-04-01 14:10:08
8440
原创 字符数组和字符串以及strlen函数
一、字符数组字符数组的定义方法字符数组是由于若干个数组元素组成的1、字符数组的定义可以类比于整型数组,定义整数数组为 int array[3] = {1,2,3};那么定义字符数组为char string[3] = {’ a ‘,’ s ',‘ f ’},这就是定义字符数组的第一种方法。2、定义字符数组的第二种方法为 char string[3] = “asdf”,对于遍历字符数组用占位符%c,输出也是一个一个的输出,示例代码如下#include<stdio.h>#include
2021-03-31 13:54:04
2022
原创 malloc函数,内存泄漏以及野指针
一、malloc函数C 语言库函数malloc原型为 void malloc(size_t size),返回一个类型为void的指针,用于申请一块连续的指定大小的内存块区域以void类型返回申请的内存地址,如果申请空间失败,返回为NULL 、malloc函数在头文件stdlib.h里面,一般将malloc函数和free函数一起使用,因为在Windows下面系统不会自动回收malloc开辟的空间,要free函数进行释放空间,在Linux下malloc在程序结束后,系统会回收这个空间。示例代码#
2021-03-29 14:29:22
985
原创 函数指针和指针函数
一、函数指针函数指针,函数的指针,也就说是一个指针,存放的是函数地址1、如何定义一个函数指针呢?a : 表示一个指针:*b : 函数的标志:()c : 函数指针是专用的,格式要求很强(参数类型,个数,返回值)void (*p)() ;就定义了一个函数指针,void表示函数的返回类型,2、如何给函数指针赋值呢?p = hello;就表示给函数指针p赋值了,add表示函数名,函数名就是地址,就像数组一样,数组名就是地址3、如何通过函数指针调用函数?a:p(); 直接通个指针名字加()调用b
2021-03-29 11:58:07
321
原创 指针数组和数组指针
1、指针数组由名字就可以知道,指针数组就是指针的数组,表示有一个数组存放多个指针,那么怎样定义一个指针数组呢?int array[3] 表示多个整数,叫整型数数组,int* parray[3] 表示多个指针,叫做指针数组,数组中的每一项元素都是指针变量,指针变量就是存放地址的变量。示例代码如下#include<stdio.h>#include<stdlib.h>int main(){ int a = 1; int b = 2; int c =
2021-03-29 10:04:29
252
1
原创 C语言数组在函数中的传参
在c语言中有时需要数组作为函数的参数进行传参,那么应该怎样传递呢?先看一下整数作为函数参数时的传参#include <stdio.h>#include <stdlib.h>int Add(int a,int b){ int c; c = a + b; return c;}int main(){ int a = 1; int b = 2; printf("%d",Add(a,b)); system("pause"); return 0;
2021-03-26 09:55:31
12459
2
原创 C语言链表的定义、遍历、增删改查、以及动态创建链表的头插法和尾插法
一、数组和链表1、什么是链表链表是一种常见的重要的数据结构,是一种存放数据的思想,它是动态地进行存储分配的一种结构,当我们用数组存放数据时必须事先定义固定的数组长度(元素个数),并且容易浪费空间,比如在不知道元素个数时,就必须把数组定义得足够大,以便能存下数据,显然这样非常浪费内存。链表就没有这种缺点,它根据需要来开辟空间。2、链表和数组的区别首先定义一个数组 int array[10],array[0]存放1、array[1]存放2,依次存放到array[9] = 10可以看到数组存放数据都是
2021-03-04 00:01:09
1103
原创 C语言为什么要用指针?
本来可以用变量名来访问变量,那为什么还要用指针呢?是不是找麻烦呢? 将从以下两点解释为什么要用指针一、指针可以向指定的地址赋值首先看一段代码#include<stdio.h>#include<stdlib.h>int main(){ int data = 10; printf("data的地址=%p\ndata = %d\n",&data,data); system("pause"); return 0;}
2021-01-17 17:04:34
2925
1
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅