向Linux登录终端发消息

同一台服务器,可能有很多个用户登录在上面,每个用户都是一个系统终端,可以向其他终端发送消息,同在服务器上开发的开发人员可以简单的互动(不能回复)一下哈!

一,效果
先登录一个终端,如下:

[root@localhost /]# who
root     tty1         2013-02-16 18:14 (:0)
root     pts/0        2013-02-17 02:01 (:0.0)
[root@localhost /]# 

登录的终端为pts/0。然后再打开一个终端,如下:

[root@localhost /]# who
root     tty1         2013-02-16 18:14 (:0)
root     pts/0        2013-02-17 02:01 (:0.0)
root     pts/1        2013-02-17 02:02 (:0.0)
[root@localhost /]#

此时登录的终端为pts/1。现在假设pts/1发消息给pts/0。

[root@localhost /]# write root pts/0
hello

在pts/0终端上收到消息如下:

[root@localhost /]#  
Message from root@localhost.localdomain on pts/1 at 02:03 ...
hello

在pts/0上只是收到消息,不能回复的。
再看一下write命令的解释吧

WRITE(1)                         User Commands                         WRITE(1)

NAME
       write - send a message to another user

SYNOPSIS
       write user [ttyname]

DESCRIPTION
       Write  allows you to communicate with other users, by copying lines from
       your terminal to theirs.

       When you run the write command, the user you are writing to gets a  mes‐
       sage of the form:
   
              Message from yourname@yourhost on yourtty at hh:mm ...

aio_read未定义的引用

下载了一份代码学习,发现编不过,这里需要修改CMakeLists.txt,可以参考编译错误: 对‘aio_read’未定义的引用

APUE 第七章 进程环境

C程序总是从main函数开始执行,main函数的原型是:
int main(int argc,char *argv[]);
其中argc是命令行参数的数目,argv是指向参数的各个指针所构成的数组。

多通道融合merge逻辑测试代码:

#include <iostream>
#include <queue>
#include <unordered_map>
#include <string>

class RecallItem {
public:
    RecallItem() {};
    RecallItem(const std::string &itemid_,const std::string &rec_id_,int score_) {
        itemid = itemid_;
        rec_id = rec_id_;
        score = score_;
    }
    std::string itemid;
    std::string rec_id;
    int score;
};

struct ItemQueue {
    std::vector<std::string> item_list;
    std::string rec_id;
};
auto item_cmp = [](const RecallItem& a,const RecallItem& b) {
    return a.score < b.score;
};

int main()
{
    std::priority_queue<RecallItem,std::vector<RecallItem>,decltype(item_cmp)> queue_item(item_cmp);
    std::unordered_map<std::string,ItemQueue > channel_map;
    //权重信息
    std::unordered_map<std::string,int > ch_weight {{"channel1",150},{"channel2",100}};
    std::unordered_map<std::string,RecallItem> item_map;
    //最大召回item个数
    int max_merge_num = 100;

    //构造两个召回通道 channel1,channel2
    auto& channel1 = channel_map["channel1"];
    channel1.rec_id = "1";
    for(int i = 0;i < 200;i+=2)
        channel1.item_list.push_back(std::to_string(i));

    auto& channel2 = channel_map["channel2"];
    channel2.rec_id = "2";
    for(int i = 1;i < 200;i+=2)
        channel2.item_list.push_back(std::to_string(i));
    //遍历多个通道
    for(auto ch : channel_map) {
        int weight = 0;
        //获取对应的权重信息
        auto it = ch_weight.find(ch.first);
        if(it != ch_weight.end()){
            weight = ch_weight[ch.first];
        }
        int index = 0,count = 0;
        int size = ch.second.item_list.size();
        //对召回列表过滤 去重 调整分数权重
        for(auto& item:ch.second.item_list) {
            double rank_score = (0+weight) * 1.0 - index++;
            auto iter = item_map.find(item);
            if(iter != item_map.end()) {
                //多个通道存在相同item,分数取较大者
                if(iter->second.score < rank_score) {
                    iter->second.score = rank_score;
                }
                //记录多个通道命中的情况
                iter->second.rec_id = iter->second.rec_id +"|" + ch.second.rec_id;
                continue;
            }
            RecallItem ch_item(item,ch.second.rec_id,rank_score);
            item_map.insert({item,ch_item});
        }
    }

    for(auto item : item_map) {
        queue_item.push(item.second);
    }

    std::vector<RecallItem> result;
    while(!queue_item.empty() && result.size() < max_merge_num) {
        auto item = queue_item.top();
        auto iter = item_map.find(item.itemid);
        if(iter != item_map.end()) {
            item.rec_id = iter->second.rec_id;
        }
        result.emplace_back(item);
        queue_item.pop();
    }

    for(auto res:result) {
        std::cout <<"itemid:"<<res.itemid<<",rec_id:"<<res.rec_id<<std::endl;
    }

#if 0
    //debug print channel_map
    for(auto ch:channel_map) {
        for(auto& item:ch.second) {
            std::cout << item <<" ";
        }
        std::cout <<std::endl;
    }
#endif

    return 0;
}