嵌入式开发完整体系课程(含项目) 扫二维码继续学习 二维码时效为半小时

(170评价)
价格: 598.00元

 posix·

#include <stdlib.h>
#Include <stdio.h>
#include <string.h>
#Include <pthread.h>

void *routine(void *arg)
{
   pthread_detach(pthread_self());
   sleep(1);
   char *msg = "abcd";
   pthread_exit((void *)msg);
}

int main(void)
{
   pthread_attr_t attr;
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

   pthread_t tid;
   pthread_create(&tid,NULL,routine,NULL);

   void *ret;
   if((errno = pthread_join(tid,&err))==0)
   {
      printf("ret:%s\n",(char *)ret);
   }
   else 
   {
      perror("pthread_join() faild");
   }
   pthread_exit(NULL);
}

 

[展开全文]
117期黄帅文 · 16天前 · 0

posix线程

每一个线程有自己独特的状态(阻塞等),但资源时共享的

pthread_create

线程的id只有在当前进程中才有效

出了这个进程就无效。

 

 

 

 

 

 

 

 

[展开全文]
117期黄帅文 · 17天前 · 0

posix有名信号量->编译时需要链接-lpthraed线程库,使用在线程间的

操作步骤

sem_open->sem_wait(P操作)/sem_post(V操作)->sem_close->sem_unlink

信号量创建后就有一个空间分别存放数据和空间内存

#include "head.h"
void shutdown_sem(int sig)
{
   sem_close(data);
   sem_close(space);

   sem_unlink(DATA);
   sem_unlink(SPACE);
   exit(0);
} 

int main(int argc,char **argv)
{
   signal(SIGINT,shutdown_sem);  
 
   int shmid = shmget(ftok(".",1),SHMSIZE,IPC_CREAT|0666);
   char *addr = shmat(shmid,NULL,0);

   sem_t *data = sem_open("/data",O_CREAT,0666,0);
   sem_t *space = sem_open("/space",O_CREAT,0666,1);
  
   char *msg = "0123456789";
   int i = 0;

   while(1)
   {
     sem_wait(space);
     memcpy(addr,msg+i,1);
     i = (i+1)%10;
     sem_post(data);
   }
   return0;
}
#include "head.h"

void shutdown_sem(int sig)
{
   sem_close(data);
   sem_close(space);

   sem_unlink(DATA);
   sem_unlink(SPACE);
   exit(0);
} 


int main(int argc,char **argv)
{
   signal(SIGINT,shutdown_sem);    //把在信号接收到的时候删除掉信号量,为的时下一次再运行的时候还可以正常跑起来
   int shmid = shmget(ftok(".",1),SHMSIZE,IPC_CREAT|0666);
   char *addr = shmat(shmid,NULL,0);

   sem_t *data = sem_open("/data",O_CREAT,0666,0);
   sem_t *space = sem_open("/space",O_CREAT,0666,1);
  
   char *msg = "0123456789";
   int i = 0;

   while(1)
   {
     sem_wait(space);
     fprintf(stderr,"%c",*addr);
     sem_post(data);
   }
   return0;
}
---------------head.h--------------
#include <>

#define static sem_t *data
#define static sem_t *space

#define DATA "/data"
#define SPACE "/space"

#define SHMSIZE 2

 

[展开全文]
117期黄帅文 · 17天前 · 0

信号量操作

int main(int argc,char **argv)
{
   int shmid = shmget(ftok(".",1),SHMSIZE,IPC_CREAT|0666);  //在当前目录下获取第一个编号的共享内存
   char *addr = shmat(shmid,NULL,0);   //注册共享内存
 
   int semid = semget(ftok(".",2),2,IPC_CREAT|0666);   //注册信号量
   union semun a;
   a.val = 0;
   semctl(semid,0,SETVAL,a);   //对信号量第一个成员设置初始值
   a.val = 1;
   semctl(semid,1,SETVAL,a);

   char *msg = "0123456789";
   int i =0;
   while(1)
   {
      memcpy(addr,msg+i,1);
      i = (i+1)%10;
   }
   return 0;
}

 

[展开全文]
117期黄帅文 · 17天前 · 0

消息队列

struct msgbuf
{
   long msgtype;
   char msg[SIZE];
}


int main(int argc,char **argv)
{
   msgget(ftok(".",1),IPC_CREAT|0666);
   struct msgbuf;
   while(1)
   { 
     bzero(&msgbuf,sizeof(msgbuf));
     fgets(msgbuf.msg,SIZE,stdin);
     msgbuf.msgtype = JACK2ROSE;

     msgsnd(msgid,msg,0);
   }
   return 0;
}
#define JACK2ROSE 1  //定义消息类型

struct msgbuf
{
   long msgtype;
   char msgtext[SIZE];
}


int main(int argc,char **argv)
{
   msgget(ftok(".",1),IPC_CREAT|0666);  //创建消息队列
//
   struct msgbuf msg;
   while(1)
   { 
     bzero(&msg,sizeof(msg));
     //fgets(msg.msg,SIZE,stdin);
     //msg.msgtype = JACK2ROSE;
     msgrcv(msgid,&msg,SIZE,JACK2ROSE,0);

//     msgsnd(msgid,msg,0);
     printf("from jack: %s",msg.msgtext);
   }
   return 0;
}

 

[展开全文]
117期黄帅文 · 18天前 · 0

信号的生命周期?

信号发送

killall xxx :杀死xxx名的进程

#include <stdio.h>
#Include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

int main(int argc,char **argv)
{
   pid_t p1;
   scanf("%d",&p1);   //p1是接受的进程号
   kill(p1,SIGINT);  //向p1进程发送SIGINT信号
//如果采用kill发送的信号不可以携带发送者的一些信息,使用sigqueue可以将发送者想要告知接收者的的信息发送出去
//其相应的接收者的处理信息函数就是采用void f(int sig,struct siginfifo....)的格式,而不是void f(int sig)
//(int sig 这个参数就是信号)。另外接收者相应的就不可以使用signal()这个函数去注册接收了,而是sigaction()
   return 0;
}
#include <stdio.h>
#Include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

void f(int sig)
{

}

int main(int argc,char **argv)
{
   pid_t p1;
   char i;
   //scanf("%d",&p1);   //p1是接受的进程号
   //kill(p1,SIGINT);  //向p1进程发送SIGINT信号
   signal(SIGINT,SIG_IGN);   //SIG_IGN忽略接收到的SIGINT信号
//   signal(SIGINT,f);   //接收到中断信号SIGINT,请内核帮忙自动执行f函数,记住f函数不是这个进程调用的,是内核调用
   sigset_t set;
   sigemptyset(&set);  //清空信号集
   sigaddset($set,SIGINT);  //往信号集添加感兴趣的信号
   sigaddset(&set,SIGHUP);
   sigprocmask(SIG_BLOCK,&set,NULL);   //将这些信号阻塞掉  //man 2 xxx查函数使用方式

   while(i<9)
   {
     i++;
     sleep(1);
   }
   sigprocmask(SIG_UNBLOCK,&set,NULL);   //解除信号阻塞,此时之前接收到的SIGINT这些信号就开始执行
   pause();   //暂停,直到信号到来
   return 0;
}
#include <stdio.h>
#Include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>

//信号携带信息的用法
void f(int sig,siginfo_t *info,void arg)
{
   printf("catch sig :%d\n",sig);
   printf("extre info: %d\n",info->si)
}

int main(int argc,char **argv)
{
   pid_t p1;
   
   struct sigaction act;
   bzero(&act, sizeof(act));
   act.sa_sigaction = f;
   act.sa_flags = SA_SIGINFO;   //这个位设置位SA_SIGINFO,的时候,才会把act.sa_sigaction替换掉act.handle函 
   //数,函数才可以使用void f(int sig,siginfo_t *info,void arg)这种格式。
   sigaction(SIGINT,&act,NULL);
   pause();   //暂停,直到信号到来
   return 0;
}
#include <stdio.h>
#Include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>

//信号携带信息的用法
void f(int sig,siginfo_t *info,void arg)
{
   printf("catch sig :%d\n",sig);
   printf("extre info: %d\n",info->si)
}

int main(int argc,char **argv)
{
   pid_t p1;
   
   scanf("%d",&p1);
   union sigval a;
   bzero(&a,sizeof(a));
   a.sival_int = 100;
   sigqueue(p1,SIGINT,a);   //携带参数的发送信号,需要上述的结构体
   return 0;
}

 

[展开全文]
117期黄帅文 · 18天前 · 0

kill -l  可以查看系统的所有信号

非实时信号:可以相互嵌套,没有优先级之分,当一个信号在处理时,再来一个相同的时候时,会被忽略掉

34及之后的是实时信号按次序接收,不嵌套,是可靠信号,一个信号发多少次就响应多少次

利用kill()可以产生任何信号

SIGKILL信号,SIGSTOP无法忽略

task_struct 进程结构体

线程被系统调度的时候才开始执行相应存在share_pending的信号

 

 

[展开全文]
117期黄帅文 · 18天前 · 0

有名管道创建后是存放在磁盘普通文件中,不会消灭

无名管道存放在内存中,会释放

#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

#define FIFONAME "myfifo"
#define SIZE 100

int main(int argc,char ** argv)
{
    if(access(FIFONAME,F_OK))   //判断文件是否存在
    {
       mkfifo(FIFONAME,0777);  //创建有名管道
    }
    int fd = open(FIFONAME,O_RDWR);
    char buf[SIZE];
    while(1)
    {
      bzero(buf ,SIZE);   //清空
      fgets(buf,SIZE,stdin);   //读取控制台的输入内容

      write(fd,buf strlen(buf));
    }
    close(fd);
    return 0;
}
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

#define FIFONAME "myfifo"
#define SIZE 100

int main(int argc,char ** argv)
{
    if(access(FIFONAME,F_OK))   //判断文件是否存在
    {
       mkfifo(FIFONAME,0777);  //创建有名管道
    }
    int fd = open(FIFONAME,O_RDONLY);
    char buf[SIZE];
    while(1)
    {
      bzero(buf ,SIZE);   //清空
    //  fgets(buf,SIZE,stdin);   //读取控制台的输入内容
      read(fd,buf,SIZE)
      //write(fd,buf strlen(buf));
      printf("from xxx %s",buf)
    }
    close(fd);
    return 0;
}

有名管道有写入原子性,也就是多个客户端或多个进程往服务器创建的有名管道写数据的时候不会乱

[展开全文]
117期黄帅文 · 18天前 · 0

fork(void )函数   创建一个新的进程

 

--------------------------------------------

atexit( )

 

 

_exit      和exit  区别

[展开全文]
高帅 · 22天前 · 0

fork( )函数

时间片    sched( )

就绪态 -----》》》》执行-----》》》》

 

 

 

wait(   )/waitpid( )

1.父进程回收释放子进程

2.获得子进程退回状态

3.同步父子进程

 

[展开全文]
高帅 · 22天前 · 0

signal函数是信号注册函数,可以通过signal提前将目标信号注册执行动作,可以设置为忽略该信号,或者收到该信号后去执行某个函数。

sigprocmask函数是设置阻塞掩码的,就是可以设置阻塞某个信号。参数中第二个参数是信号集,说明可以阻塞多个信号,只要放在信号集中就可以,该函数也可以设置不阻塞信号,只需要修改第一个参数中的宏即可。

信号集的设置可以使用信号集操作函数簇,第一步清空信号集sigemptyset,然后调用sigaddset将指定信号添加到信号集中。

sigqueue函数也是用来发送信号的,只是可以携带更多发送者的信息。sigqueue和sigaction是配套使用的。相当于kill和signal的增强版。

sigaction也是注册函数,功能和signal一样,只不过注册的是f'函数,是带有额外信息的信号触发函数。

[展开全文]
王布斯 · 06-13 · 0

1. kill -l可以查看系统中所支持的信号

2.信号中从1-31所有的信号都是有特殊含义的(也叫非实时信号或者不可靠信号)(信号之间没有优先级,是可以嵌套使用的)(处理这一类的信号时,如果系统正在处理一个信号,此时有同种类型的信号又发送过来时,系统会自动忽略掉,只当又发送过来的同样的信号不存在)

3.后面的34-64之间的信号没有特殊含义(也叫可靠信号或者实时信号)(实时信号是有顺序的,按次序接收,不嵌套,按顺序处理不会被打断)

4.在shell命令中给一个进程发信号的命令是:kill -s 信号名(或者是信号的值,比如9) 进程PID号

5.ps -ef查看当前进程信息

6.如果同时开启了好多个同样的进程,可以使用命令killall 进程名    来同时杀死多个进程

7.sigset是一个信号的集合

sourceinsight软件中按ctrl键加鼠标左键,可以进入变量的定义中去

按alt+,(逗号)可以返回之前界面。

linux中查询信号的默认动作,shell命令是man 信号编号(如9) signal。

[展开全文]
王布斯 · 06-11 · 0

vim中按shift+k,会跳转到一个同名的变量或函数的man手册中。

创建有名管道的函数接口是mkfifo("file_name",mode);

创建完毕后使用open函数打开就可使用。

判断是否已经创建有有名管道文件的函数是access(const char *pathname, int mode);

[展开全文]
王布斯 · 06-10 · 0

exec函数簇的功能是父进程中调用,当需要子进程执行的代码量很大时,父进程中并不执行这些代码,但需要包含这些以复制给子进程,造成空间浪费,这时可以调用exec函数,参数中传入想要执行的程序或者路径,子进程就会照着这个路径去找执行程序,父进程中就不需要写太多多余的代码,导致空间浪费。

execl函数中的参数,第一个是可执行程序的路径,第二个是参数,执行程序本身就是参数,所以需要再写一遍,最后要写上NULL。函数传参的基本方式就是,argv[0] argv[1](如果有的话) NULL。

execv函数中的参数,是提前将传参的参数封装到一个数组中,将数组名传递给execv函数。

execlp函数可以执行shell命令,p是环境变量path的意思。

[展开全文]
王布斯 · 06-10 · 0

可执行程序运行时,输入命令./test程序会运行在前台进程组,输入命令./test &时,程序会运行在后台进程组,即后台运行,程序后台运行时,shell终端发出的命令比如ctrl+c是影响不了test进程运行的,但是计算机断电或者关闭终端,这种后台进程是可以被杀掉的

ps -ef命令可以查看当前的进程执行情况

使用精灵进程(守护进程)的目的是为了一个进程,需要他持续不断的运行,尽管终端关闭,他也能在后台运行,满足工作需求

[展开全文]
王布斯 · 06-10 · 0

1.进程僵尸是指进程退出后,他占用的资源并没有被立即释放掉。之所以不立即释放资源是因为子进程需要发送信号给他的父进程报告他是怎么死的,以及他的任务完成的情况,他占用的资源等信息保留在task_struct结构体中。子进程只有死亡状态时他占用的资源才会被回收释放掉。没有释放之前叫僵尸态。

2.父进程在子进程进入僵尸态后调用wait/waitpid函数来对子进程收尸,执行的操作有:读取里面的数据获得子进程任务执行的状况;获得子进程的退出状态;同步父子进程

[展开全文]
王布斯 · 06-10 · 0

pipe();

无名管道有两个端口,读写分开

 

 

[展开全文]
WG豪 · 11-26 · 0