精华内容
下载资源
问答
  • JAVA实现与Linux通信(通过SSH协议)

    千次阅读 2011-12-29 18:04:55
    使用InputStream和OutputStream来获得命令行运行结果和输入内容是首先需要具备的. 然后要解决SSH连接问题. 在OpenSource项目里找到了Ganymed SSH-2 for Java .下载后有例子,但是没有找到...Linux修改密码输入passwd后
     
    
    使用InputStream和OutputStream来获得命令行运行结果和输入内容是首先需要具备的.
    然后要解决SSH连接问题.
    在OpenSource项目里找到了Ganymed SSH-2 for Java .下载后有例子,但是没有找到有关交互命令的例子.所以自己探索了一下
    在网上看有老外讨论用这个如何改密码,基本上的问题都是因为找不到返回的提示
    Linux修改密码输入passwd后,首先是输入当前密码,然后是输入两个新密码
    如果当前密码输入错误,或者新密码输入不符合系统密码规则要求,会要求重新输入.如果碰到这种情况,程序很容易进入一个不太好控制的循环.
    可能一般人都认为输入命令后所有的返回都应该是用session.getStdout();而不是session.getStderr();从方法名称上看确实如此,一个是取得标准输出,一个是取得错误信息.
    其实在输入passwd后.
    Changing password for user [username].
    Changing password for [username]
    这两行是需要通过session.getStdout();来获得的.但是后面的
    (current) UNIX password:
    New UNIX password:
    Retype new UNIX password:
    这三行是需要使用sessssion.getStderr();来获取的
    如果用户输入没有通过系统检测,会返回具体原因,但是都是BAD PASSWORD开始的.
    如果最后修改成功了.你也会看到有successfully来表示.这些信息是通过session.getStdout();来获取的.
    现在问题很好解决了吧.
    写了一个类来完成修改密码的操作
    Java代码
    import ch.ethz.ssh2.Connection;
    import ch.ethz.ssh2.Session;
    import ch.ethz.ssh2.StreamGobbler;
    import com.io.Debug;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    /**
     *
     * @author leon.lee
     */
    public class ChangeEmailPassword {
        private String username = "";
        private String oldpassword = "";
        private Connection conn = null;
        private boolean hasError = false;
        private String ErrorMessage = "";
        private boolean isSuccessfully = false;
        private String SystemMessage = "";
        
        public static final String HOST = "127.0.0.1"; //server ip
        public boolean isSuccessfully(){
            return isSuccessfully;
        }
        public boolean isHasError(){
            return hasError;
        }
        public String getErrorMessage(){
            return ErrorMessage;
        }
        public void setErrorMessage(String msg){
            hasError = true;
            this.ErrorMessage =  msg;
        }
        /**
         * Creates a new instance of <code>ChangeEmailPassword</code>.
         * @param username
         * @param oldpassword
         */
        public ChangeEmailPassword(String username,String oldpassword) {
            this.username = username;
            this.oldpassword = oldpassword;
             try{
                 conn = new Connection(HOST);
                 conn.connect();
                /* Authenticate */
                boolean isAuthenticated = conn.authenticateWithPassword(username, oldpassword);
                if (isAuthenticated == false) {
                    setErrorMessage("Authentication failed.");
                    conn=null;
                }
             }catch(Exception e){
                 conn.close();
                 conn = null;
                 System.out.println(e);
             }
        }
        public void setNewPassword(String newpassword) {
            if(hasError){
                return;
            }
            if (conn==null){
                return;
            }
            try{
                Session sess = conn.openSession();
                sess.execCommand("passwd");
                InputStream so = sess.getStdout();
                InputStream err = sess.getStderr();
                OutputStream out = sess.getStdin();
                
                byte[] buffer = new byte[500];//其实没有必要这么大.130就差不多了.怕万一有什么提示.
                int length = 0;
                length = err.read(buffer);
    //            if (length > 0) {
    //                System.out.println("#1:"+ new String(buffer, 0, length));
    //                //(current) UNIX password:
    //            }
                String coldpassword = oldpassword+"\n";
                out.write(coldpassword.getBytes());
                length = err.read(buffer);
    //            if (length > 0) {
    //                System.out.println("#2:"+ new String(buffer, 0, length));
    //                //(current) UNIX password:
    //            }
                String cnewpass = newpassword +"\n";
                out.write(cnewpass.getBytes());
                length = err.read(buffer);
                if (length > 0) {
                    String rs = new String(buffer, 0, length);
                    //System.out.println("#3:"+rs);
                    if(rs.indexOf("BAD")>-1){
                        sess.close();
                        conn.close();
                        setErrorMessage(rs);
                        return;
                    }
                }
                out.write(cnewpass.getBytes());
                length = so.read(buffer);
                if (length > 0) {
                    String rs = new String(buffer, 0, length);
                    if(rs.indexOf("successfully")>-1){
                        this.isSuccessfully = true;
                        this.SystemMessage = rs;
                    }
                }
                /* Close this session */
                sess.close();
                /* Close the connection */
                conn.close();
            } catch (IOException e) {
                e.printStackTrace(System.err);
            }
        }
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            ChangeEmailPassword cep = new ChangeEmailPassword("username", "oldpassword");
            if(cep.isHasError()){
                System.out.println(cep.getErrorMessage());
                cep = null;
                return;
            }
            cep.setNewPassword("newpassword");
            if(cep.isHasError()){
                System.out.println(cep.getErrorMessage());
                cep = null;
                return;
            }
            if(cep.isSuccessfully){
                System.out.println(cep.getSystemMessage());
            }
        }
        /**
         * @return the SystemMessage
         */
        public String getSystemMessage() {
            return SystemMessage;
        }
    }
    
     
    把里面注解掉的System.out.println打开可以看到系统提示的信息.我只保留了最关键的信息提示
    展开全文
  • Linux CAN通信

    千次阅读 2017-07-19 09:31:02
    Linux CAN通信  实现了Linux下的CAN通信——初始化,发两个送和接收(采用队列形式),使用两个线程,还有一个超时响应目前未写。接收部分使用select实现。 #ifndef _CAN_H_ #define _CAN_H_ #include #include...

    Linux CAN通信


            实现了Linux下的CAN通信——初始化,发两个送和接收(采用队列形式),使用两个线程,还有一个超时响应目前未写。接收部分使用select实现。


    #ifndef _CAN_H_
    #define _CAN_H_
    
    #include <stdio.h>
    #include <sys/ioctl.h>
    #include <arpa/inet.h>
    #include <net/if.h>
    #include <linux/socket.h>
    #include <linux/can.h>
    #include <linux/can/error.h>
    #include <linux/can/raw.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <time.h>
    #include <pthread.h>
    #include "can_queue.h"
    #include "type.h"
    
    #ifndef AF_CAN
    #define AF_CAN 29
    #endif
    #ifndef PF_CAN
    #define PF_CAN AF_CAN
    #endif
    
    typedef enum
    {
      CAN_PORT_0 = 0, // can0
      CAN_PORT_1,     // can1
    }can_port_t ;
    
    typedef struct
    {
      char *name;
      int fd;
      fd_set fdsr;
    
      pthread_t send_thread;
      pthread_t recv_thread;
      pthread_t time_thread;  
    
      can_queue_t *send_queue; // 接受和发送的队列
      can_queue_t *recv_queue;
    } can_t;
    
    void *CanInit(int arg);
    
    #endif /* _CAN_H_ */
    
    #include "can.h"
    
    static can_t *can_init(int name)
    {
      int ret;
      struct sockaddr_can addr;
      struct ifreq ifr;
      struct can_filter rfilter[1];
      can_t *current = (can_t *)malloc(sizeof(can_t));
    
      current->fd = Socket(PF_CAN, SOCK_RAW, CAN_RAW);
      sprintf(ifr.ifr_name, "can%d", name);
      current->name = (char *)malloc(6);
      memset(current->name, 0, 6);
      sprintf(current->name, "can%d", name);
    
      ret = ioctl(current->fd, SIOCGIFINDEX, &ifr);
    
      if(ret < 0)
      {
        exit(0);
      }
    
      addr.can_family = AF_CAN;
      addr.can_ifindex = ifr.ifr_ifindex;
      Bind(current->fd, (struct sockaddr *)&addr, sizeof(addr));
    
      rfilter[0].can_id = 0x2;
      rfilter[0].can_mask = 0;
      Setsockopt(current->fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
    
      return current;
    }
    
    static void *can_send_thread(void *arg)
    {
      int ret;
      can_t *current = arg;
      can_frame_t frame;
      uint8_t read_ret = 0;
    
      while(1)
      {
        Write(current->fd, &frame, sizeof(frame));
        read_ret = current->send_queue->can_read(current->send_queue, &frame);
        if(CAN_OK == read_ret)
        {
          ret = Write(current->fd, &frame, sizeof(frame));
          usleep(1200);
        }
        usleep(100);
      }
    
      return NULL;
    }
    
    static void *can_recv_thread(void *arg)
    {
      int ret, i;
      can_frame_t frame;
      struct timeval tv;
      fd_set rset;
      can_t *current = arg;
    
      while (1)
      {
        tv.tv_sec = 0;
        tv.tv_usec = 200;
    
        FD_ZERO(&rset);
        FD_SET(current->fd, &rset);
        ret = select(current->fd + 1, &rset, NULL, NULL, NULL);
    
        if (0 == ret)
        {
          return NULL;
        }
    
        ret = read(current->fd, &frame, sizeof(frame));
    
        if (ret < sizeof(frame))
        {
          return NULL;
        }
    
        if (current->recv_queue->can_write(current->recv_queue, &frame) == CAN_ERROR)
        {
         
        }
      }
    
      return NULL;
    }
    
    void *CanInit(int arg)
    {
      can_t *current = can_init(arg);
    
      current->recv_queue = CanQueueInit(CAN_RECV_QUEUE_SIZE);
      current->send_queue = CanQueueInit(CAN_SEND_QUEUE_SIZE);
    
      pthread_create(&current->send_thread, NULL, can_send_thread, (void *)current);
      pthread_create(&current->recv_thread, NULL, can_recv_thread, (void *)current);
    }
    



    展开全文
  • Linux 进程通信

    万次阅读 2018-05-06 14:31:38
    Linux 进程通信 1.传统进程通信 1.1 信号 信号机制是在软件层次上对中断机制的一种模拟。 信号的捕获与处理也成为系统的“软中断”机制。 1.1.1 常用信号 每个信号都有一个编号和宏定义的名称,这些名字...

    Linux 进程通信

    1.传统进程通信

    1.1 信号

    信号机制是在软件层次上对中断机制的一种模拟。
    信号的捕获与处理也成为系统的“软中断”机制。

    1.1.1 常用信号

    每个信号都有一个编号和宏定义的名称,这些名字都已SIG开头。宏定义在signal.h头文件中。

    1.1.2 信号的处理

    缺省操作,默认的信号处理方式。SIG_DFL
    忽略信号,进程忽略接收到的信号,但SIGKILL和SIGSTOP不能忽略。SIG_DFL
    捕获信号,提供一个信号处理函数,而不是使用默认的信号处理方式。要求内核此时切换到用户态。

    CUP的两种状态:内核态和用户态
    点击这里有详细介绍

    1.1.3 信号处理函数
    1. signal() 定义进程收到信号后的处理方法
    #include<signal.h>
    void (*signal(int signum, void(*func)(int)))(int);

    signum: 信号名称,整数值
    func:一个指针,指向信号处理函数。该参数还可以是SIG_DFL或SIG_IGN(前者为默认的缺省操作的函数,后者为默认的忽略信号的函数)
    调用成功,返回原来的信号处理函数的指针;失败则返回SIG_ERR

    1. kill() 向进程或进程组发送一个信号
    #include<signal.h>
    int kill(pid_t pid, int sig);

    pid: 接收信号的进程ID。当pid为0时,发送给与当前进程同组的所有进程。
    sig: 信号名称
    信号发送成功返回0;信号发送失败返回-1。

    1.2 管道

    连接两个进程的连接器,数据在其中单向流动。

    1.2.1 普通管道

    位于内存中。只能用于有亲缘关系进程(父子进程)之间的单向通信。
    当一个管道建立后,将获得两个文件描述符,分别用来对管道进程读取和写入。通常将其称为管代的写入端和管道的读取端。

    这里的写入端和读取端指的是对管道的写入和读取。

    pipe() 创建一个普通管道

    #include<unistd.h>
    int pipe(int filedes[2])

    filedes[0]: 读端口的文件描述符
    filedes[1]: 写端口的文件描述符
    调用成功返回0;调用失败返回-1。

    普通管道读写规则:
    1. 读规则
    关闭管道的写端: close (fd[1])
    读出: read(fd[0], buf, size); 从管道读端口fd[0]读出size个字符放到buf中
    读出后关闭管道的读端: close(fd[0])
    2. 写规则
    关闭管道的读端: close(fd[0])
    写入: write(fd[1], buf, size); 把buf中的长度为size的字符送到管道写端口fd[1]
    写入后关闭管道的写端: close (fd[1])

    两个进程通过一个管道只能实现单向通信,如果需要父子进程双向通信,就必须另打开一个管道。
    在管道满时,写管道操作将被阻塞;在管道空时,读管道操作将被阻塞。

    例子:

    /*
     * 利用两个管道进行双向通信,实现父子进程协作把整数x1加到10
     */
    #include<unistd.h>
    #include<sys/types.h>
    #include<stdlib.h>
    #include<stdio.h>
    int main()
    {
        int x = 1;
        int pipe1[2], pipe2[2];
        pid_t val;
        pipe(pipe1);
        pipe(pipe2);
        if((val = fork()) <0 )
            exit(1);
        if(val == 0)
        {
            close(pipe1[1]);
            close(pipe2[0]);
            while(x<=9)
            {
                read(pipe1[0], &x, sizeof(int));
                printf("Child:%d, read:%d\n", getpid(), x++);
                write(pipe2[1], &x, sizeof(int));
            }
            close(pipe1[0]);
            close(pipe2[1]);
        }
        else
        {
    
            close(pipe2[1]);
            close(pipe1[0]);
            while(x<=10)
            {
                write(pipe1[1], &x, sizeof(int));
                read(pipe2[0], &x, sizeof(int));
                printf("Parent:%d, read%d\n", getpid(), x++);
    
            }
            close(pipe2[0]);
            close(pipe1[1]);
        }
        return 0;
    }
    
    1.2.2 命名管道

    位于文件系统中。可以实现不同进程间的双向通信。

    mkfifo() 创建命名管道,将产生一个FIFO文件

    #include<sys/types.h>
    #include<unistd.h>
    int mkfifo(const char * pathname, mode_t mode);

    pathname:创建的FIFO文件名
    mode:规定FIFO文件的读写权限
    调用成功时返回0;调用失败返回-1

    命名管道必须同时读和写,否则会阻塞

    2. System V IPC 进程通信

    2.1 IPC

    进程间通信(Inter-Process Communication)

    2.1.1 查看ipc对象的信息

    ipcs [-asmq]
    -a:all,查看全部的IPC对象信息
    -s:signal,查看信号量集
    -m:memory,查看共享内存
    -q:queue,查看消息队列

    IPC标识符由内核分配给IPC对象,在系统内部唯一,给系统看
    IPC关键字由程序员选择,全局唯一,给人看,32字长
    每个进程都可以建立一个键值为IPC_PRIVAE的私有IPC对象

    ftok() 生成唯一的键值

    #include<sys/types.h>
    #include<sys/ipc.h>
    key_t ftok(char *filename, int id);

    filename:文件名,可以使用绝对路径或相对路径
    id:整型变量。可通过指定相同文件的文件名和不同的整型变量,生成不同的键值。
    调用成功返回所生成的键值;失败返回-1。

    /*
     *
     利用消息队列实现父子进程的通信。
     父进程创建消息队列,并向消息队列发送消息;子进程接受消息;
     父进程等待子进程接收消息后删除消息队列。
     *
     */
    #include<stdio.h>
    #include<stdlib.h>
    #include<sys/types.h>
    #include<sys/msg.h>
    #include<string.h>
    struct msgbuf{
        long msgtype;
        char msgtext[255];
    };
    
    int create_queue(int key)
    {
        int qid = -1;
        if(key == -1)
            perror("ftok");
        else if( (qid= msgget(key, IPC_CREAT|0666)) < 0)
            perror("msgget");
        else return qid;
    }
    
    void  send_message(int qid, struct msgbuf *msg, char *message)
    {
        strcpy(msg->msgtext, message);
        if(msgsnd(qid, msg, strlen(msg->msgtext), 0) < 0)
            perror("msgsnd");
    }
    
    void recive_message(int qid, struct msgbuf *msg)
    {
        memset(msg->msgtext, 0, 255);
        if(msgrcv(qid, msg, sizeof(msg->msgtext), msg->msgtype, 0) < 0)
            perror("msgrcv");
    }
    
    void distory_queue(int qid)
    {
        struct msqid_ds qds;
        if(msgctl(qid, IPC_RMID, &qds) < 0)
            perror("msgctl");
    }
    
    int main()
    {
        struct msgbuf msg;
        int qid;
        pid_t pid;
        key_t key = ftok(".", 1);   //生成唯一的键值
        msg.msgtype = 1;
        qid = create_queue(key);
        pid = fork();
        if(pid < 0)
            perror("fork");
        else if(pid > 0)
        {
            send_message(qid, &msg, "This is the input!");
            printf("Parent: Send to the message queue successfully!\n");
            printf("The message sent is :%s\n", msg.msgtext);
            wait(NULL);
            distory_queue(qid);
        }
        else
        {
            recive_message(qid, &msg);
            printf("Clild: Receiving from the message queue:%s\n", msg.msgtext);
        }
    
    
        return 0;
    }
    

    2.2 消息队列

    以异步方式为通信频繁但数据量少的进程通信提供服务
    存储消息得的线性表,按照先进先出的原则,对数据输入输出。

    系统中消息队列最多个数:256
    每条消息的最大字节数:8KB
    每个队列能容纳的最大字节数:16KB

    2.2.1 消息结构模板msgbuf

    include/linux/msg.h

    struct msgbuf
    {
        long msgtype;   //消息类型
        char mtext[1];  //消息内容,可自行定义消息的长度
    };
    2.2.2 基本操作:
    1. 创建或打开消息队列:msgget()
    #inclide<sys/types.h>
    #include<sys/msg.h>
    int msgget(key_t, int flags);

    key:键值
    flags:标识和权限信息的组合。若标识部分为0,则获取一个已存在的消息队列的标识符;若为IPC_CREAT:如果消息队列不存在则创建,存在则引用。
    调用成功,返回消息队列的标识符;否则,返回-1。

    1. 向消息队列发送消息:msgsnd()
    #inclide<sys/types.h>
    #include<sys/msg.h>
    int msgsnd(int msgid, struct msgbuf *msgp, size_t size, int flag);

    msgid:消息队列的标识符
    msgp:指向消息结构的指针
    size:消息内容的长度
    flag:发送消息可选标志。若flag为0,则当消息队列满时,发送操作阻塞;若为IPC_NOWAIT时,当消息队列满时,立即返回-1。
    调用成功,返回0;否则,返回-1。

    1. 从消息队列读出消息:msgrcv()
    #inclide<sys/types.h>
    #include<sys/msg.h>
    int msgrcv(int msgid, struct msgbuf *msgp, \
                  size_t size, long type, int flag);

    msqid:消息队列的标识符
    msgp:消息结构指针
    size:要读取消息的长度
    type:要读取消息的类型
    flag:接收消息可选标志。若flag为0,当消息队列为空时,进程阻塞;若flag为IPC_NOWAIT,当消息队列空时,进程不阻塞,立即返回-1;若flag为MSG_NOERROR,当消息长度大于接收缓冲区长度,截断消息返回,小于等于则不接受该消息,出错返回。
    调用成功,返回实际读取到的消息数;否则,返回-1。

    1. 删除消息队列:msgctl()
    #include <sys/msg.h>
    int msgctl(int msgid, int cmd, struct msgid_ds *buf);

    msgid:消息队列的标识符
    buf:指向msgid_ds结构的指针
    cmd:控制命令。若cmd为IPC_RMID, 则删除消息队列;若为IPC_STAT,则获取消息队列的结构,保存在buf所指向的缓冲区中;若为IPC_SET,则按照buf指向的结构来设置该消息队列的结构。
    调用成功,返回0;否则,返回-1。
    获取和修改消息队列属性信息
    查询消息队列描述符
    修改消息队列许可权
    删除该队列等

    2.3 共享主存

    2.4 信号量集

    远程通信

    展开全文
  • Linux进程通信基本概念 从原理上来看,进程通信的关键技术就是在进程间建立某种共享区,利用进程都可以访问共享区的特点来建立一些通信通道。如下图所示: 其实,以前设计程序时使用的全局变量,就是一种可以在...

    Linux进程通信基本概念

    从原理上来看,进程通信的关键技术就是在进程间建立某种共享区,利用进程都可以访问共享区的特点来建立一些通信通道。如下图所示:

    其实,以前设计程序时使用的全局变量,就是一种可以在各个函数之间进行通信的手段,它所占用的内存空间就是程序中各个函数的共享区。但那时,由于各个函数都同属于一个进程,因此没有进程空间的障碍。所以,解决进程之间通信的就在于如何突破进程空间的障碍。

    其实,在某些特殊情况下,两个进程之间并没有空间障碍。例如:用fork()创建了一个子进程之后,子进程与父进程尚未完全脱离关系之前,子进程和父进程处于同一个进程空间,这时是完全可以向定义一个全局变量来定义一个通信通道的,以实现父子进程之间的通信。虽然这是自然形成的一个结果,但并不是操作系统的功劳,却给人们一个启示:可以利用子进程创建伊始会与父进程共享一些资源(例如文件)的特点来构建通信通道,Linux在这方面的成果就是“管道”。

    父子进程利用共享资源进行通信的示意图如下:

    对于那些具有进程空间障碍的进程通信可以利用页框共享技术来实现。例如,一个由3个进程共享的页框示意图如下:

    另外,还可以当进程处于内核期间利用内核空间来进行通信,例如:

    总之,通信的关键就是想办法在进程之间创建共享区域来传递数据。

     

    System V IPC机制简介

    Linux的通信手段基本都继承自Unix。历史上对Unix的发展做出重大贡献的两大主力:AT&T的贝尔实验室和加州大学伯克利分校(BSD)。在通信方面,前者主要对单个计算机内的进程通信机制进行了改进和扩充,形成了System V IPC;后者则主要在计算机间,基于嵌套字(socket)的进程间通信机制方面做出了重要贡献。

    早期的Unix IPC包括管道、FIFO和信号,后期的System V IPC则主要包括System V消息队列、System V信号量集和System V共享内存。

    Linux从一开始就严格遵守Unix的设计思路,从而形成了Linux通信机制,如下图所示:

    Linux进程通信的主要手段有:

    • 匿名管道(pipe)以及命名管道(named pipe):匿名管道可用于具有亲属关系进程间的通信;命名管道克服了匿名管道没有名称的限制,从而允许无亲属关系进程间的通信;
    • 信号(signal):信号是一种通知性的通信方式,当某种事件发生时,用于向接收进程发出通知,根据需要,接收进程可以对通知做出某种反应,也可以不加任何理睬;
    • 消息队列:消息队列是由多个信号组成的链表,而消息是一种有结构的数据。与信号比,消息队列能承受更大的信息量;与管道比,消息队列克服了管道只能承载无格式字节流以及缓冲区大小受限的缺点。比较完备;
    • 共享内存:共享内存是多个进程可以共同访问一块内存空间,是最快的通信方式。但它不具备同步和互斥机制,往往需要程序上使用信号量或锁与它配合;
    • 信号量集(semaphore):主要作为进程间以及同一进程不同线程之间的同步方式;
    • 嵌套字(socket):主要用来实现网络上不同机器之间的通信。

    在上述System V IPC通信机制中,通常将通信装置叫做IPC(Inter-Process Communication,进程间通信)对象。为了对这些对象进行统一管理,系统为他们定义了一些统一的数据结构和标识。

    IPC标识符

    在IPC中,对于消息队列、共享内存和信号量集这些IPC对象,都用非负的整数来作为对象的标识。不同种类对象的标识是各自独立编制的,即同一个标识符可能代表共享内存,也可能代表消息队列或信号量集。

    IPC键值

    为了能唯一的标识一个对象,在IPC中,每创建一个对象还要为其指定一个键值,这个键值是一个长整型数。

    kern_ipc_perm结构

    系统为每一个IPC对象,都为其创建一个描述该对象基本信息的ipc_perm结构。该结构主要用于访问权限检查。kern_ipc_perm的定义如下:

    struct kern_ipc_perm
    {
    	spinlock_t	lock;
    	int		deleted;
    	int		id;                    
    	key_t		key;                      //对象的键值
    	uid_t		uid;                      //用户标识
    	gid_t		gid;                      //用户组标识
    	uid_t		cuid;                     //对象创建者的用户标识
    	gid_t		cgid;                     //对象创建者的用户组标识
    	mode_t		mode;                     //对象的操作权限
    	unsigned long	seq;                      //已创建的IPC对象的数目
    	void		*security;                //与对象标识相关的序列号
    };

    当一个对象被创建时,kern_ipc_perm除了seq之外的所有域都会被赋予相应的数值。在对象存在期间,IPC对象的创建者和超级用户,可以调整控制函数xxxctl()来修改kern_ipc_perm结构中的属性。控制函数名称中的xxx的含义如下图所示:

    IPC对象的生命期

    IPC对象是全局对象,对象一经创建就由系统进行管理,它们的生命期与创建它的进程生命期无关。

    IPC对象的操作函数

    为了实现对象的操作,系统在函数库中为用户提供了一个IPC对象操作函数ipc()。其原型如下:

    int ipc(uint call, int first, int second, int third, void __user *ptr, long fifth);

    ipc()中的第一个参数call叫做操作码。不同的操作码对应着不同的IPC对象的不同操作函数。该操作码定义如下:

    #define SEMOP		 1
    #define SEMGET		 2
    #define SEMCTL		 3
    #define SEMTIMEDOP	 4
    #define MSGSND		11
    #define MSGRCV		12
    #define MSGGET		13
    #define MSGCTL		14
    #define SHMAT		21
    #define SHMDT		22
    #define SHMGET		23
    #define SHMCTL		24

    凡是以SEM开头的操作码都表示信号量集操作函数,以MSG开头的都表示是消息队列操作函数,以SHM开头的都表示是内存共享操作函数。

    其实,上述这种用操作码来区分不同对象的不同操作并不方便(至少使程序的可读性变差)。所以,Linux系统函数库又分别定义了12个函数来完成不同的操作。其中,用于信号量集的函数为semop()、semget()、semctl()、semtimedop();用于消息队列的函数为msgsnd()、msgrcv()、msgget()、msgctl();用于共享内存的函数为shmat()、shmdt()、shmgat()、shmctl()。

     

    展开全文
  • Linux进程间通信

    千次阅读 2019-04-21 08:00:23
    进程间通信11.1进程间通信介绍11.2Linux内核提供的进程间通信机制11.3管道11.4SystemV IPC介绍 11.进程间通信 11.1进程间通信介绍 进程间通信(IPC)指的是2个任意进程之间的通信。进程用户空间是相互独立的,一般...
  • 最近做嵌入式系统,需要用到tar解压显示进度,tar解压显示进度可以用linux shell脚本做出来,但是生产那边需要在液晶上面看到解压进度,然后在设备上移植了ucgui。ucgui没有额外的依赖第三方库,可以看成一个标准c写...
  • Linux 管道通信

    千次阅读 2011-09-09 21:04:07
    一、定义  管道是单向的、先进先出的。它将一个程序的输入和另一个程序的输出连接起来。...前者用于父进程和子进程间的通信,后者用于同一系统的两个进程间通信。   二、无名管道  int pi
  • linux进程间通信

    千次阅读 2016-10-10 14:29:15
    windows+linux进程间通信方式
  • Linux进程通信

    千次阅读 2012-08-08 09:28:15
    linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同。...
  • Linux C++ 串口通信

    万次阅读 2018-05-22 11:23:52
    说明 随着嵌入式开发在物联网行业中站的比重日益增加,Linux 环境下的C++...就好比这里要介绍的串口通信, 在Windows开发中, 无论是C++, MFC,还是C#, 巨硬大大都给我们做好了封装。可是在Linux下就没那么简单了,...
  • Linux进程间通信——管道通信

    千次阅读 2019-05-05 18:36:48
    1. 进程间通信概述 进程间通信(Inter-Process Communication, IPC)是指在两个或者多个不同得劲进程间传递或者交换信息,通过信息的传递建立几个进程间的联系,协调一个系统中的多个进程之间的行为。 1.1 进程间...
  • linux进程通信---无名管道

    千次阅读 2013-07-02 16:43:10
    Linux通信方式主要从unix继承而来,而对unix发展做出巨大贡献的是AT&T和BSD,前者主要是对早期的unix进程间通信进行系统的改进和升级,形成了system V IPC,这种通信方式主要是单个计算机内,而后者则跳出了这个限制...
  • Linux进程通信之消息队列的双向通信

    千次阅读 2017-06-12 16:05:36
    上一篇博客我写了进程间通信基于管道的通信,但是管道的通信无疑有很大的缺点,最显著的就是只能单向通信,例如:server向client发消息,client无法回复;第二个就是只能在有血缘关系的进程间进行通信,虽然命名管道...
  • 一、linux下进程间通信的几种主要手段简介: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘...
  • Linux 之管道通信

    千次阅读 2018-08-26 00:45:03
    管道通信使用先入先出的原则进行读写,且不能是lseek函数定位读写位置。 (1)无名管道,无名管道是一种特殊类型的文件,完全由操作系统管理和维护,因为其存储位置只有亲缘关系的进程知道,所以只能用于亲缘关系的...
  • linux 蓝牙通信开发,作为请求蓝牙连接一方,是不是必须输入PIN码,如果必须输入PIN码,linux下有没有可以调用的接口或配置文件来写入PIN码。linux下做过蓝牙通信的大侠来给解答一下吧,谢谢!!
  • Linux 4G模块通信

    千次阅读 2020-02-20 14:46:33
    4G模块大都是采用了MiniPCIE接口,实际上通信接口都是USB,4G模块驱动对应的就是USB驱动。4G模块厂商都提供了详细的文档讲解如何在linux下使用4G模块,以及如何修改Linux内核加入4G模块驱动。 一、硬件原理图 4G...
  • linux进程间通信概述

    千次阅读 多人点赞 2011-10-07 10:09:12
    linux进程间通信(IPC)有几种方式,下面将将简单的简述一下:   一.管道(pipe) 管道是Linux支持的最初IPC方式,管道可分为无名管道,有名管道等。 (一)无名管道,它具有几个特点: 1) 管道是半双工的,...
  • Linux:串口通信

    千次阅读 2011-08-03 13:04:22
    以前跟着做过VxWorks的开发,主要通信方式是串口,因为底层BSP包已经...后来接触Linux,在一块OK6410上跑Linux串口通信,才发现原来天真的以为甚是简单的串口变得如此的不简单。 1、串口的操作  1.1打开:fd = open
  • Linux下串口收发通信

    万次阅读 多人点赞 2018-09-19 01:47:15
    串口通信流程:打开串口ttySn---&gt;初始化串口---&gt;读写(read、write)---&gt;关闭串口 最合适的指导书:https://www.ibm.com/developerworks/cn/linux/l-serials/ 串口设置 最基本的设置串口...
  • Linux 进程间通信的机制

    千次阅读 2018-07-30 15:27:04
    Linux 下进程间通信的6种机制:  1.管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间...
  • 我在2两台虚拟机上分别运行linux 服务端和客服端socket程序,客户端和服务端能正常通信,但是我用wireshark 抓包时确没抓到有这两个虚拟机的通信包,请问高手们这个是啥情况??
  • linux进程间通信的几种机制的比较及适用场合 1.# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。# 有名管道 (named pipe...
  • 套接口(Socket)为目前Linux上最为广泛使用的一种的进程间通信机制,与其他的Linux通信机制不同之处在于除了它可用于单机内的进程间通信以外,还可用于不同机器之间的进程间通信。但是由于Socket本身不支持同时等待...
  • Linux进程通信(一)——pipe管道

    万次阅读 2017-02-14 20:30:29
    什么是进程通信进程通信就是两个进程之间进行数据交换,在Linux中有好几种可以进行进程通信的方式,在这篇文章中我们主要介绍最基本的进程通信方式——pipe管道。进程通信的途径进程之间交换信息的唯一途径就是传送...
  • linux进程间通信精讲

    千次阅读 2012-11-17 21:03:55
    linux进程间通信简介  进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源。但是,进程不是孤立的,不同的进程之间需要信息的交换以及状态的...
  • linux中的网络通信指令

    千次阅读 2015-07-06 16:02:55
    1.writewrite命令通信是一对一的通信,即两个人之间的通信,如上图。效果图用法:write <用户名>2.wallwall指令可将信息发送给每位同意接收公众信息的终端机用户效果图 wall是将一个文件的内容发送出去3.ping 选项 ...
  • Linux进程通信之管道和FIFO

    千次阅读 多人点赞 2013-07-20 16:51:23
    Linux进程间的通信可以简称为IPC(Interprocess Communication),前面说过的 Linux的同步工具也是属于IPC的一部分,这里我想说的是通常意义的进程间的实际数据通。 1管道 管道是最早的UNIX IPC,所有的UNIX系统...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 414,284
精华内容 165,713
关键字:

linux通信

linux 订阅