Tag Archives: Конспекти

Корисні налаштування Git

Перше. Як не задовбувати всіх сміттям яке створює ваше IDE, і за замовчуванням мати gitignore для всіх репозиторіїв.

git config --global core.excludesfile ~/.gitignore

Ця команда відредагує файл ~/.gitconfig і в ~/.gitignore можна буде перелічити всякі там *.swp, чи що там ваш редактор створює.

Друге. Якщо Go не хоче встановлювати модулі з помилкою “fatal: could not read Username for ‘https://github.com’: terminal prompts disabled”, бо залежності прописані через https, а ви використовєуте SSH, це можна виправити таким налаштуванням:

git config --global url."git@github.com:".insteadOf "https://github.com/"

На цьому поки що все, дякую за увагу. 🙂

Kubernetes з microk8s

Kubernetes – це такий docker-compose на стероїдах, що дозволяє керувати кластером машин на яких запускаються контейнери. Infrastructure as a code, і всяке таке. Дивно що в цьому кібернетичному блозі про кібернетіс ще жодного разу не згадувалось, тому варто цю ситуацію виправити.

Інсталяція

Є різні способи поставити локально однонодовий кластер, minikube (з яким в мене не дуже вийшло), і microk8s, який на Ubuntu, і лінукси в яких є менеджер пакетів Snappy, ставиться так:

sudo snap install microk8s --classic

Це встановить кластер і CLI для керування кластером kubectl. Правда вона називатиметься microk8s.kubectl. Якщо ви не ставили kubectl окремо (можна через той же snap install) для керування кластером десь в хмарах, то можна зробити аліас, а якщо ставили – так можна переконфігурити її для роботи з локальним кластером:

microk8s.kubectl config view --raw > ~/.kube/config

Тоді можна наприклад отримати список нодів кластера:

$ kubectl get nodes
NAME                   STATUS    ROLES     AGE       VERSION
bunyk-latitude-e5470   Ready     <none>    3h        v1.14.0

Логічно що у випадку локальної інсталяції це буде лише один комп’ютер.

Щоб перемкнути kubectl на керування наприклад якимось кластером в хмарах Google, за умови що у вас встановлений gcloud, треба виконати:

gcloud container clusters get-credentials [CLUSTER_NAME]

Аддони й панель керування

Ще microk8s має команди для вмикання (enable) і вимикання (disable) аддонів:

microk8s.enable dns dashboard

dns потрібний для багатьох речей, тому його радять вмикати. dashboard – web UI, і InfluxDB з Grafana для моніторингу ресурсів. Щоб його побачити, треба викликати kubectl proxy і перейти за адресою: http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login

Сторінка логіну

Там попросять залогінитись, щоб отримати JWT токен для логіну, треба виконати

kubectl -n kube-system get secret
# тоді в списку знайти ім'я що починається з kubernetes-dashboard-token-
# а тоді:
kubectl -n kube-system describe secret kubernetes-dashboard-token-c4bmp

Параметр -n означає простір імен, це щось на зразок директорії де лежать всі об’єкти кластера, наприклад секрети. Це також відображається в шляхах до API, як от /api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/ для доступу до сервісу https:kubernetes-dashboard. За замовчуванням kubectl працює з простором імен default, але у випадку вище, нам треба kube-system.

Запуск контейнерів в Kubernetes

Тепер може спробуємо щось запустити? Для цього треба створити под (pod – англійське слово що позначає групу китів. Вони взагалі дивні слова мають для цього. Зграя сов – це parliament, круків – murder). Под – це група контейнерів зі спільною IP адресою, які запускаються а ноді.

Найпростіший спосіб створити под – майже такий самий як запустити контейнер:

kubectl run nginx --image=nginx
# kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
# deployment.apps/nginx created

Це говорить нам що команда створила deployment, але в майбутньому створюватиме лише поди, якщо не передати параметр --generator=run-pod/v1. Чому так пояснюють тут.

Що таке деплоймент? Нуууу, це важко пояснити, і це мене найбільше в Кубернетісі вибішує. Под – це набір конейнерів зі спільною IP адресою, набором портів, диском, і т.д. Под сам по собі запускати в kubernetes не рекомендують, бо після того як в нього трапиться якась аварія наприклад через закінчення пам’яті, його ніхто не перезапустить. Подом керує контролер, одним з яких є контролер що називається ReplicaSet, який задає кількість копій пода що мають бути запущені. І якщо одна з них з якихось причин здихає – запускається нова, щоб кількість завжди відповідала потрібній. Deployment – об’єкт що містить контролер ReplicaSet, і керує версіями імеджів контейнерів в подах цього контролера. Абстракцій як в TCP/IP…

Тим не менш, ми побачимо под в списку:

$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7db9fccd9b-w6468   1/1     Running   1          44h

Щоб видалити деплоймент разом з подами дають команду:

kubectl delete deployments/nginx

Трохи складніший спосіб створити под – написати маніфест:

apiVersion: v1 
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - image: nginx
      name: nginx
      ports:
        - containerPort: 80
          name: http
          protocol: TCP

Якщо його записати в файл, наприклад nginx.yaml, то щоб запустити:

kubectl apply -f nginx.yaml 

Як подивитись що всередині пода? Можна прокинути порт, і тоді те що контейнери в поді віддають на якомусь порті буде доступно на порті localhost:

kubectl port-forward nginx 8088:80

Загальне правило для портів в Kubernetes (бо такі пари порт:порт зустрічаються часто) – зліва порти ззовні, справа – всередині. Якщо все працює, на http://localhost:8088 ви маєте побачити сторінку де пише “If you see this page, the nginx web server is successfully installed and working.”

Можна подивитись логи:

$ kubectl logs -f nginx
127.0.0.1 - - [31/Mar/2019:17:00:53 +0000] "GET /favicon.ico HTTP/1.1" 404 154 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0" "-"
127.0.0.1 - - [31/Mar/2019:17:01:56 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0" "-"

Як змінити те що под показує на головній? Створити якийсь html файл і закинути його командою:

kubectl cp index.html nginx:/usr/share/nginx/html/index.html

Хоча так не прийнято робити, і можна хіба що під час розробки. Краще додати файли в імедж за допомогою Dockerfile.

Запуск сайту

Але давайте вже зробимо щось серйозне на кілька контейнерів. Наприклад як в цій публікації було за допомогою docker compose, тільки за допомогою kubernetes: два контейнери, один з них nginx веб-сервер що віддає статичні файли для фронт-енду, інший – API на python що віддає дані графіків.

Таким чином файли backend.docker, dashboard.html і server.py можна скопіювати собі в проект без змін (звідси). nginx.docker напевне краще називати frontend.docker, і помістити туди лише файли фронт-енду:

FROM nginx

COPY dashboard.html /usr/share/nginx/html/index.html

Конфігурацію nginx ми змінювати не будемо, бо відповідальним за диспетчеризацію запитів між фронт-ендом і бекендом в нас буде штука що називається Ingress.

Тут, на відміну від docker-compose який сам наші контейнери може зібрати, їх треба створити вручну:

docker build -t frontend -f frontend.docker .
docker build -t backend -f backend.docker .

Покладемо конфіг для двох деплойментів у файл site.yaml і скажемо кластеру оновитись (kubectl apply -f site.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
spec:
  selector:
    matchLabels:
      tier: frontend
  replicas: 1
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: frontend
        image: frontend
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deployment
spec:
  selector:
    matchLabels:
      tier: backend
  replicas: 2 # більше подів для бекенду, бо йому самому може важко.
  template:
    metadata:
      labels:
        tier: backend
    spec:
      containers:
      - name: backend
        image: backend
        ports:
        - containerPort: 80

Один файл в Kubernetes може містити описи багатьох об’єктів, розділені рядком що містить “—“. Так простіше працювати, бо треба менше команд kubectl apply, чи kubectl delete.

Якщо kubectl get pods показує що наші поди мають статус ErrImagePull або ImagePullBackOff, це означає що kubernetes намагається взяти імеджі не з нашого комп’ютера, а з докерхабу.

Виявляється треба ще додати їх в реєстр microk8s. Для цього:

microk8s.enable registry

docker tag backend localhost:32000/backend
docker push localhost:32000/backend
docker tag frontend localhost:32000/frontend
docker push localhost:32000/frontend

Підозрюю що це можна було зробити простіше і швидше якщо зразу називати імеджі правильним тегом. Але майстерність приходить з досвідом. 🙂 В кінцевому результаті ви маєте мати три запущені поди, в двох деплойментах.

І що з того? Поки нічого, бо IP адреси цих подів динамічно міняються (коли їх перезапускають). Для того щоб мати постійний доступ потрібен сервіс, який проксює доступ до подів заданих мітками (labels). Мітки це пари ключ-значення які чіпляються до об’єктів в Kubernetes. Коли ми в описі пода писали:

labels: 
  tier: backend

То це ми йому якраз задавали мітки. Тепер по мітках ми можемо ці об’єкти отримувати:

bunyk@bunyk-thinkpad:~/projects/dockerizing$ kubectl get pods -l tier=frontend
NAME                                   READY   STATUS    RESTARTS   AGE
frontend-deployment-695cfcc94c-jl5hg   1/1     Running   0          3h6m
bunyk@bunyk-thinkpad:~/projects/dockerizing$ kubectl get pods -l tier=backend
NAME                                  READY   STATUS    RESTARTS   AGE
backend-deployment-669d885465-cfbrc   1/1     Running   0          3h6m
backend-deployment-669d885465-nh8lg   1/1     Running   0          3h6m

Так само сервіс має надає доступ з постійним IP до набору подів заданого мітками. Сервіси створюються так:

apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  selector:
    tier: backend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  selector:
    tier: frontend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

Сервіс має селектор що визначає за якими подами стежити, і відкриває порти. port – це який порт відкрити, targetPort – це до якого порта в поді приєднатись. За цим треба слідкувати, бо якщо не виконається одна з умов: порт на якому слухає сервер в контейнері == containerPort, containerPort == targetPort сервіса, port сервіса == порт до якого приєднується клієнт, то отримаємо помилку “Connection refused” чи подібну.

Після чергового kubectl apply -f site.yaml можна подивитись які сервіси отримуємо:

$ kubectl get services
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
backend      ClusterIP   10.152.183.69   <none>        80/TCP    110m
frontend     ClusterIP   10.152.183.63   <none>        80/TCP    30m
kubernetes   ClusterIP   10.152.183.1    <none>        443/TCP   8d
$ curl 10.152.183.69/data/1
[1.0997977838,0.6222197737,0.7265324166,1.0475918458,0.8271129655,0.6489646475,0.3625859258,0.7692987393,1.1331619921,1.4889188394]

Бачимо що сервіси які ми створюємо мають тип ClusterIP. Це тип за замовчуванням, і означає що він буде доступний лише з середини кластера. Нам доступний, бо ми ж сидимо на одній єдиній ноді кластера. Крім нього є ще NodePort, LoadBalancer і ExternalName, але розбиратись що це – ми не будемо, бо й без того голова вже пухне (чи у вас ні?).

Залишився ще Ingress. Це штука що дає доступ до сервісів кластера ззовні кластера. Конфігурується так:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: entrypoint
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - http:
      paths:
      - path: /api/(.*)
        backend:
          serviceName: backend
          servicePort: 80
      - path: /(.*)
        backend:
          serviceName: frontend
          servicePort: 80

Тут важливий параметр nginx.ingress.kubernetes.io/rewrite-target, який означає “передавати сервісу запит замінивши URL на той що вказано, підставивши групи з регулярного виразу в path“.

Після застосування цієї конфігурації, на localhost в нас завантажиться фронтенд, пошле через ingress запити до бекенду, і все навіть буде через HTTP 2.0.

Питайтесь якщо що не виходить чи не доходить, в мене теж багато з того що тут написано не виходило зразу, може я вже стикався з тими проблемами що у вас.

Як відсканувати книжку без сканера?

Є класний додаток для андроїд від Microsoft – Office Lens. Він робить деякі зусилля щодо того аби криво (під якимось кутом) сфотографовані документи виглядали як відскановані. Це звісно важче для книжки, особливо якщо багато сторінок обдерті і не прямокутні, але часто виглядає краще ніж просто фото, і потім обрізати менше.

Знімки програми потім можна буде знайти на пристрої за шляхом /Pictures/Office Lens.

А зліпити їх до купи і перетворити в DJVU – за допомогою скрипта, який я запозичив звідси і трохи модифікував:

import os, glob, subprocess

#Change these to suit your situation=========================
IMGDIR="./" #directory of images to be converted
OUTDJVU = IMGDIR + 'OUT.djvu'

#Don't change these ==========================================
TMPDJVU = IMGDIR + 'TMP.djvu'


#convert jpg to djvu and collate to a single file   
if os.path.exists(OUTDJVU):
    os.remove(OUTDJVU)

for infile in sorted(glob.glob(os.path.join(IMGDIR, '*.jpg'))):
    print('Processing ' + infile)

    #convert jpg to a temp djvu file
    # cmd = 'c44 -decibel 48 ' + '"'+infile+'"' + ' "'+TMPDJVU+'"'
    subprocess.call(['c44', '-decibel', '48', infile, TMPDJVU])
    
    if os.path.exists(OUTDJVU):
        #Add the djvu file to the collated file
        cmd = ['djvm', '-i', OUTDJVU, TMPDJVU]
    else:
        # Create the collated file
        cmd = ['djvm', '-c', OUTDJVU, TMPDJVU]
    subprocess.call(cmd)

#Delete the temporary file
os.remove(TMPDJVU)

print('\nAll files converted and collated successfully')

В результаті можна отримати щось отаке: https://commons.wikimedia.org/wiki/File:%D0%A7%D0%B8%D1%82%D0%B0%D0%BD%D0%BA%D0%B0_%D0%B4%D0%BB%D1%8F_II._%D0%BA%D0%BB._%D1%88%D0%BA._%D1%81.djvu

Ethernet на хлопський розум

I’m a web crawling spider; you an Internet mosquito;
You thought the 7-layer model referred to a burrito.
You’re a dialup connection; I’m a gigabit LAN.
I last a mythical man-month; you a one-minute man.

Monzy – “kill -9

Іноді аби щось зрозуміти, іноді мало читати, треба писати. Сьогодні ми розберемось чим комутатор та міст відрізняються від концентратора. :) Я хотів добре розібратись як працює маршрутизатор, але це ще рівнем вище, і ця вся справа затягнулась.

Рівні мережевої моделі

Почнемо з рівнів. Комп’ютерні мережі такі складні, що зрозуміти їх цілком дуже важко, тому вирішили розділити їх на рівні абстракції. Цих рівнів можна нарахувати від п’яти до семи, але ми почнемо з перших двох.

Перший рівень – фізичний. На цьому ми домовляємось скільки вольт – це нуль, а скільки – одиничка, чи може це взагалі буде лазер в оптоволокні, або радіохвиля. Використовувати частотну, чи амплітудну модуляцію? Це все фізичні аспекти. Також цей рівень за допомогою різноманітних кодувань, вирішує як довго триває одиничка або нуль, і як відрізнити послідовність 11111 від послідовності 111111?

Таким чином, якщо ми обрали середовище фізичного рівня – виту пару, радіо, чи оптоволокно, ми знаємо що якщо ми передамо 01, то хтось прийме 01 і саме в такому порядку.

Далі йде другий рівень – канальний. Так як і в спілкуванні людей, треба серед всіляких звуків середовища розрізняти слова, особливо сказані до тебе, так і тут, треба серед усіх нулів і одиничок треба виділити окремі повідомлення, і визначити хто з ким говорить. Для цього домовляються про послідовності біт на зразок “Dixi” (я все сказав), “Шо?” (здається лінія зашумлена, повторіть передачу). І “так я сказав те що ви почули” (контрольна сума).

А також визначають хто коли говорить. Тому що до одного каналу (проводу чи ефіру) зазвичай під’єднано два і більше комп’ютерів, і коли вони передають дані одночасно, то ніхто нікого не чує.

Контроль доступу до середовища

Визначенням того хто коли говорить займається підрівень (який взагалі то другий, але його чомусь виділяють) Media access control (контроль доступу до середовища, MAC), і є різні способи:

  • Наприклад передавати по колу токен (мікрофон), і давати право говорити лише тому, в кого токен. Після чого він має передати токен наступному вузлу мережі, і так далі по колу. Така схема називається Token ring.
  • Переважно люди які знаходяться в одній кімнаті спочатку слухають, і якщо ніхто не говорить – починають говорити. Якщо сигнал передано успішно – добре, а якщо хтось почав говорити одночасно з нами (сигнал поширюється середовищем певний час) – доведеться почекати випадковий час і спробувати ще раз.

    Такий протокол називається Carrier sense multiple access (CSMA), 1-persistent. Перекладається як множинний доступ з відчуттям носія і зухвальством-1. Відчуття носія означає що ми слухаємо провід. Зухвальство 1 означає що ми ліземо вставити свої 5 копійок, як тільки випаде нагода. Це не оптимально щодо кількості колізій. Протокол зі зухвальством 0.5 з ймовірністю 50% замість того щоб передавати, вирішує почекати і послухати ще один такт. Тому що коли на лінії одна машина передає, і своєї черги чекають 10, то з зухвальством буде дуже важко добитись наступної передачі без колізій.

    В Ethernet (найпопулярніший протокол для побудови мережі) використовується CSMA/CD – Carrier Sense Multiple Access with Collision Detection, тобто те саме що я описав, тільки вони вміють виявляти колізію за формою сигналу, ще до того як передасться ввесь кадр з контрольною сумою.

Ethernet

Тепе поговоримо детальніше про стандарти першого і другого рівня – Ethernet. Ehternet – це назва стандарту IEEE 802.3, і частка Ether – (етер), там на честь ефіру (якого насправді не існує, лише вакуум).

Але Ethernet існує і його створили в 1976 Роберт Меткальф та Девід Боґґс в дослідницькому центрі Xerox. (Ця компанія так багато винайшла! Шкода що їх знають лише за копіювальними апаратами). Швидкість передачі була 3 Мбіт/с.

В 1978 Dell, Intel та Xerox створили стандарт DIX, який описував 10 Мбіт/с Ethernet.

В 1983-му стандарт DIX став називатись IEEE 802.3. Меткальф заснував власну компанію 3com і почав продавати Ethernet адаптери.

Ethernet має обмеження на довжину кабеля, яке можна обійти за допомогою повторювачів – пристроїв фізичного рівня, які просто посилюють сигнал. З точки зору канального рівня кабель з повторювачами не відрізняється від звичайного. Але все одно є обмеження на час передачі сигналу, після якого не можливо усунути колізії.

По кабелю Ehternet сигнал передається в манчестерському коді. Інформація формується в кадри, формат яких описано на вікіпедії.

Для роботи колізій використовували CSMA/CD зухвалості 1. Станція слухає канал і якщо чує тишу – передає. Якщо сталась колізія чекає випадкову кількість інтервалів. Інтервал = 2t, де t – час протягом якого сигнал поширюється від одного кінця кабелю до іншого. Якщо кількість колізій 10 – очікують від 0 до 1023 інтервалів. Якщо i > 16 – повертають помилку.

Комутований Ethernet

2550T-PWR-Front
З часом користувачі Ehternet виявили що приєднання купи комп’ютерів до одного кабеля має недолік, що обрив кабеля псує роботу всієї мережі. І придумали концентратор (хаб). Концентратор відрізняється від повторювача тим, що має більше ніж два порти, а так принцип той самий – сигнал який входить на один порт, виходить на всіх інших підсиленим до потрібного рівня. З точки зору канального рівня мережа з концентратором виглядає як один кабель, всі комп’ютери під’єднані до концентратора містяться в одному просторі колізій, а тому чим більше комп’ютерів в мережі, тим повільніше вона працюватиме.

І нарешті, Ethernet запозичив в телефонних мереж ідею комутації, та з’явився свіч (мережевий комутатор). На відміну від концентратора, свіч посилає кадр лише тій станції, якій він призначений. А також, на відміну від хаба, в свічі кожна станція потрапляє у свій простір колізій, тому їх кількість зменшується до одиниці. Так як кадри з різних портів можуть прямувати на один порт, свіч містить буфер і відправляє їх по черзі. Ще одна корисна властивість свіча – він запобігає підслуховуванню чужих кадрів за допомогою адаптера в promiscuous mode.

До свіча можна приєднати хаб, таким чином на одному порті свіча буде ніби кілька станцій. Свіч на це реагує просто ігноруючи кадри, які адресуються станції підключеній до того самого хаба що й станція яка відправила кадр.

Хоча сьогодні, хаби (концентратори) майже зовсім не використовуються, тому можна вважати що один кабель завжди з’єднує лише два пристрої.

Fast, Gigabit Ethernet

Після того як з’явився комутований Ethernet, швидкість мережі перестала падати за нелінійним законом при приєднанні нових комп’ютерів і люди почали звикати до швидкості 10 Мбіт/c.

В 1992-му IEEE доручив комітету 802.3 створити новий стандарт, помноживши швидкість на 10. В 1995-му вийшов стандарт 802.3u, відомий в народі як Fast Ethernet. Який дозволяв передавати дані зі швидкістю 100 Мбіт/с. Свічі звісно мусили підтримувати обидва стандарти і щоб визначити який з них можна застосовувати на порті використовували процедуру яка називається “autonegotiation”.

Далі Fast Ethernet звісно став недостатньо швидким, і його знову вирішили помножити на 10. В 1999 IEEE випустили стандарт 802.3ab, або Gigabit Ehternet, що передавав 1 Гбіт/с, як не важко було здогадатись. В ньому заборонили використовувати концентратори і дуже скоротили кабелі (максимальна довжина 25м), тому що при такій швидкості можна відправити цілу купу кадрів до того як проявляться перші ознаки того що відбувається колізія. (мінімальний розмір кадру – 64 байти.)

Але 25 метрів це дуже мало, тому щоб збільшити, до стандарту дописали що можна дописувати ще одне поле, яке розширяє кадр до 512 байт (carrier extension) і використовувати кабелі до 200м. Але передавати 512 байт, де корисні лише 64 дуже неефективно. тому також пробували склеювати кадри в пакети (frame bursting).

Також в Gigabit Ethernet є функція контролю потоку. Якщо кадри йдуть з Gigabit в класичний Ethernet, свіч може послати передавачу на Gigabit порті кадр PAUSE (кадр в якому в полі тип написано 0x8808), щоб передавач пригальмував.

А далі, в 2002, 2004 та 2006 роках з’явились стандарти 10-гігабітного Ethernet для оптоволокна, екранованого мідного кабелю і мідної витої пари. І працюють над ще швидшими! Але ми в ті деталі сьогодні не вдаватимемось.

Мости

Коли ми розглядаємо мережі, треба завжди розглядати два аспекти – фізичний і логічний. Фізичний – це те як ми прокладаємо кабелі і які пристрої ними з’єднуємо. Логічний – як кадри всередині кабелів рухаються і комутуються насправді. Ми можемо як розділити одну фізичну мережу на кілька логічних, так і з’єднати кілька фізичних в одну логічну. Мости займаються останнім.

До появи комутованого Ethernet, мережа – це був кабель, в який комп’ютери вгризались за допомогою пристрою що називався “вампірчик” (прочитайте про кабель 10BASE5). Але кабель має обмежену довжину, і йому дозволено обмежену кількість повторювачів. Так само організація може займати кілька приміщень, і помістити всі комп’ютери в одну мережу, хай навіть і за допомогою комутатора, буде накладно. В таких випадках кожне приміщення отримує фізичну мережу, які з’єднуються між собою за допомогою моста.

Міст працює в нерозбірливому режимі (promiscuous mode), тобто приймає всі кадри, не залежно від того кому він призначався. І далі вирішує що з ним робити, шукаючи потрібну інформацію в спеціальній таблиці.

При приєднанні моста до мереж, ця таблиця порожня. Як тільки на якийсь з портів приходить кадр, міст запам’ятовує в таблиці MAC-адресу відправника і номер порта, і розсилає кадр на всі порти окрім того на який кадр прийшов (як хаб).

Якщо хтось відповідає, і просить прислати кадр на MAC-адресу яка мосту вже відома, міст шле кадр лише на відому адресу.

Якщо з якоїсь MAC-адреси вже кілька хвилин не приходили кадри, міст видаляє запис з таблиці, таким чином якщо фізична конфігурація мережі змінюється, міст сам за кілька хвилин переучується.

У вас напевне виникло питання “А чим відрізняється міст і комутатор?”. А тим самим що й ноутбук та лептоп – в слові комутатор більше букв :). Просто дві різні назви з’явились історично.

Метою мостів було з’єднувати різні мережі (наприклад Token Ring і Ethernet), але виходило погано, тому переважно вони з’єднували однокабельні Ethernet мережі, або Ethernet мережі з концентраторів. А метою комутаторів було замінити концетратори, які мали обмеження на число з’єднань пов’язане з котролем доступу до середовища. Але в кінці вийшло одне й те ж.

Spanning tree protocol (STP)

Слово “міст” (bridge) використовується й досі, тому що його використовують в актуальних досі стандартах, наприклад IEEE802.1D. Це стандарт що описує те як повинні працювати мости, і зокрема, такі деталі як протокол кістякового дерева.

Ми можемо з’єднувати два мости (концентратори) більш ніж одним кабелем для збільшення надійності з’єднання. Але тоді з’являється проблема – широкомовні кадри зацикляться, бо міст отримуватиме кадр через один порт і відправлятиме на всі інші, таким чином, якщо два мости з’єднані через два порти, вони пересилатимуть цей кадр одне одному, і всім іншим приєднаним пристроям до нескінченності.

Тому, мости домовляються ігнорувати лінії які не входять в кістякове дерево. Для цього, обирається кореневий свіч (свіч з найменшим ID, яким є MAC), і знаходяться всі найкоротші (найшвидші) лінії які ведуть від кожного пристрою до кореневого свіча. Це й є кістякове дерево.

Радья Перлман що придумала цей алгоритм змогла також віршик написати:

A tree that must be sure to span
So packets can reach every LAN.
First, the root must be selected.
By ID, it is elected.
Least-cost paths from root are traced.
In the tree, these paths are placed.

Взагалі, хотів би я вміти писати вірші. Їх справді легше й веселіше запам’ятовувати. Саме за допомогою вірша я вперше зміг запрограмувати рендеринг фракталу Мандельброта.

VLAN

Окрім того що багато фізичних локальних мереж можна об’єднати в одну логічну, можна також поділити одну фізичну, на багато логічних. Причин для цього є кілька:

  • Безпека (ізоляція даних)
  • Зменшення навантаження при доставці широкомовних пакетів. Такі пакети часто зустрічаються, бо потрібні наприклад для роботи протоколу ARP.
  • Локалізація можливого %D0%BE%D0%B2%D0%BD%D0%B8%D0%B9_%D1%88%D1%82%D0%BE%D1%80%D0%BC">широкомовного шторму та інших неполадок.
  • Працівник може перевестись з одного офісу в інший (наприклад ближче до дому), і потрапити в іншу фізичну мережу. Але йому все одно треба бути в логічній мережі свого відділу.

Всі ці проблеми намагається вирішити технологія VLAN (віртуальної локальної мережі).

Комутатор що підтримує VLAN позначає (“зафарбовує”) кожен порт, як такий що належить певній VLAN (або кільком). На схемах VLAN позначають кольором, щоб можна було одночасно відобразити фізичну і логічну топології. Якщо приходить кадр з наприклад “червоної” VLAN, і він широкомовний, або порт для MAC-адреси отримувача невідомий, то його відправляють на всі порти які належать “червоній” VLAN.

Що робити якщо порт прибуває через порт що належить кільком VLAN? Кадр може належати лише одній мережі, але якій? Для цього, IEEE погодився змінити формат кадру Ethernet і додати туди нове поле. Стандарт випущений в 1998 назвали IEEE 802.1Q.

Найважчим питанням було, а що робити з мільйонами мережевих плат які не підтримують цей формат кадру? Щоб не викидати існуюче мережеве обладнання вирішили що перший комутатор на шляху кадра, що сумісний з VLAN буде додавати в кадр ідентифікатор VLAN, а останній – забирати. Таким чином на кінцеве обладнання потрапляють кадри звичайного формату.

VLAN який присвоюють кадру визначають за тим з якого порта він прийшов, або за протоколом вищого рівня. Наприклад можна послати всі кадри що містять IP в одну мережу, а кадри з PPP – в іншу. Було б зручно також визначати VLAN за MAC-адресою (наприклад якщо ноутбук часто змінює порти), але стандарт 802.1Q такого не передбачає.

Поле ідентифікатора для VLAN займає 12 біт. Таким чином загальна кількість можливих VLAN – 4096. Цього недостатньо для хмарних сервісів які дозволяють створювати мільйони віртуальних серверів і мереж, тому для них придумали іншу технологію віртуалізації – VXLAN (Virtual eXtensible LAN). Але в ній вже самі кадри віртуальні і передаються всередині TCP-пакетів. Віртуалізується віртуальна мережа. :)

Вищі рівні

Мости/комутатори це пристрої другого рівня. Вони дивляться на заголовки кадрів і таким чином вирішують що з ними робити. Концентратори і повторювачі – пристрої першого рівня. Вони просто приймають і передають сигнали, не особливо задумуючись над тим що ті сигнали означають.

З’єднати мережі з різними протоколами складно, бо переклад навіть чогось формального – дуже складна задача. Це ускладнюється різним максимальним розміром порції даних дозволених для передавання (MTU), різною схемою адресації і багато чим іншим. Але крім трансляції одного протоколу в інший, є ще один спосіб.

Щоб справді з’єднати мережі різного типу (наприклад 802.11 (Wi-Fi), 802.3 (Ethernet) та MPLS (швидкісний протокол що з’єднує комутатори провайдерів)), треба використати ще один рівень абстракції. Навіть якщо на другому рівні пристрої адресуються не за допомогою MAC, вони все одно адресуються спільними адресами третього рівня (наприклад IP). На цьому рівні абстракції працює маршрутизатор (router). Він відкидає всі заголовки кадрів другого рівня, і дивиться в їх вміст. А вміст – це датаграма третього рівня, і її заголовки вона описують куди її відправити.

Існують також пристрої ще вищого рівня, які називаються шлюзами. Існують шлюзи транспортного рівня, що дозволяють перетворювати дані з одного протоколу в інший, або шлюзи прикладного рівня, що, наприклад перетворюють SMS-повідомлення в E-mail.

Джерела

Всіх посилань не даю, бо їх забагато. В основному “Комп’ютерні мережі” Танненбаума і вікіпедія.

До читачів

Cподіваюсь я не переобтяжив ваші мізки інформацією і загальні принципи ви зрозуміли. Дякую що дочитали сюди і не заснули. І пробачте що так мало картинок – мені треба оновити свою стару Xubuntu 12.04, і подивитись чи в ній працюватиме графічний планшет. Тоді сподіваюсь цей блог стане більш ілюстрованим.

Якщо маєте ще якісь питання – питайтесь, я поки це все писав, таки трохи розібрався. Деталі звісно на вікіпедії, і якщо читатимете її українською, почистіть трохи те що читатимете, бо в телекомунікаціях там такий срач, що руки за голову хапаються.


Filed under: Конспекти, Павутина Tagged: hardware

Ethernet на хлопський розум

I’m a web crawling spider; you an Internet mosquito;
You thought the 7-layer model referred to a burrito.
You’re a dialup connection; I’m a gigabit LAN.
I last a mythical man-month; you a one-minute man.

Monzy – “kill -9

Іноді аби щось зрозуміти, іноді мало читати, треба писати. Сьогодні ми розберемось чим комутатор та міст відрізняються від концентратора. :) Я хотів добре розібратись як працює маршрутизатор, але це ще рівнем вище, і ця вся справа затягнулась.

Рівні мережевої моделі

Почнемо з рівнів. Комп’ютерні мережі такі складні, що зрозуміти їх цілком дуже важко, тому вирішили розділити їх на рівні абстракції. Цих рівнів можна нарахувати від п’яти до семи, але ми почнемо з перших двох.

Перший рівень – фізичний. На цьому ми домовляємось скільки вольт – це нуль, а скільки – одиничка, чи може це взагалі буде лазер в оптоволокні, або радіохвиля. Використовувати частотну, чи амплітудну модуляцію? Це все фізичні аспекти. Також цей рівень за допомогою різноманітних кодувань, вирішує як довго триває одиничка або нуль, і як відрізнити послідовність 11111 від послідовності 111111?

Таким чином, якщо ми обрали середовище фізичного рівня – виту пару, радіо, чи оптоволокно, ми знаємо що якщо ми передамо 01, то хтось прийме 01 і саме в такому порядку.

Далі йде другий рівень – канальний. Так як і в спілкуванні людей, треба серед всіляких звуків середовища розрізняти слова, особливо сказані до тебе, так і тут, треба серед усіх нулів і одиничок треба виділити окремі повідомлення, і визначити хто з ким говорить. Для цього домовляються про послідовності біт на зразок “Dixi” (я все сказав), “Шо?” (здається лінія зашумлена, повторіть передачу). І “так я сказав те що ви почули” (контрольна сума).

А також визначають хто коли говорить. Тому що до одного каналу (проводу чи ефіру) зазвичай під’єднано два і більше комп’ютерів, і коли вони передають дані одночасно, то ніхто нікого не чує.

Контроль доступу до середовища

Визначенням того хто коли говорить займається підрівень (який взагалі то другий, але його чомусь виділяють) Media access control (контроль доступу до середовища, MAC), і є різні способи:

  • Наприклад передавати по колу токен (мікрофон), і давати право говорити лише тому, в кого токен. Після чого він має передати токен наступному вузлу мережі, і так далі по колу. Така схема називається Token ring.
  • Переважно люди які знаходяться в одній кімнаті спочатку слухають, і якщо ніхто не говорить – починають говорити. Якщо сигнал передано успішно – добре, а якщо хтось почав говорити одночасно з нами (сигнал поширюється середовищем певний час) – доведеться почекати випадковий час і спробувати ще раз.

    Такий протокол називається Carrier sense multiple access (CSMA), 1-persistent. Перекладається як множинний доступ з відчуттям носія і зухвальством-1. Відчуття носія означає що ми слухаємо провід. Зухвальство 1 означає що ми ліземо вставити свої 5 копійок, як тільки випаде нагода. Це не оптимально щодо кількості колізій. Протокол зі зухвальством 0.5 з ймовірністю 50% замість того щоб передавати, вирішує почекати і послухати ще один такт. Тому що коли на лінії одна машина передає, і своєї черги чекають 10, то з зухвальством буде дуже важко добитись наступної передачі без колізій.

    В Ethernet (найпопулярніший протокол для побудови мережі) використовується CSMA/CD – Carrier Sense Multiple Access with Collision Detection, тобто те саме що я описав, тільки вони вміють виявляти колізію за формою сигналу, ще до того як передасться ввесь кадр з контрольною сумою.

Ethernet

Тепе поговоримо детальніше про стандарти першого і другого рівня – Ethernet. Ehternet – це назва стандарту IEEE 802.3, і частка Ether – (етер), там на честь ефіру (якого насправді не існує, лише вакуум).

Але Ethernet існує і його створили в 1976 Роберт Меткальф та Девід Боґґс в дослідницькому центрі Xerox. (Ця компанія так багато винайшла! Шкода що їх знають лише за копіювальними апаратами). Швидкість передачі була 3 Мбіт/с.

В 1978 Dell, Intel та Xerox створили стандарт DIX, який описував 10 Мбіт/с Ethernet.

В 1983-му стандарт DIX став називатись IEEE 802.3. Меткальф заснував власну компанію 3com і почав продавати Ethernet адаптери.

Ethernet має обмеження на довжину кабеля, яке можна обійти за допомогою повторювачів – пристроїв фізичного рівня, які просто посилюють сигнал. З точки зору канального рівня кабель з повторювачами не відрізняється від звичайного. Але все одно є обмеження на час передачі сигналу, після якого не можливо усунути колізії.

По кабелю Ehternet сигнал передається в манчестерському коді. Інформація формується в кадри, формат яких описано на вікіпедії.

Для роботи колізій використовували CSMA/CD зухвалості 1. Станція слухає канал і якщо чує тишу – передає. Якщо сталась колізія чекає випадкову кількість інтервалів. Інтервал = 2t, де t – час протягом якого сигнал поширюється від одного кінця кабелю до іншого. Якщо кількість колізій 10 – очікують від 0 до 1023 інтервалів. Якщо i > 16 – повертають помилку.

Комутований Ethernet

2550T-PWR-Front
З часом користувачі Ehternet виявили що приєднання купи комп’ютерів до одного кабеля має недолік, що обрив кабеля псує роботу всієї мережі. І придумали концентратор (хаб). Концентратор відрізняється від повторювача тим, що має більше ніж два порти, а так принцип той самий – сигнал який входить на один порт, виходить на всіх інших підсиленим до потрібного рівня. З точки зору канального рівня мережа з концентратором виглядає як один кабель, всі комп’ютери під’єднані до концентратора містяться в одному просторі колізій, а тому чим більше комп’ютерів в мережі, тим повільніше вона працюватиме.

І нарешті, Ethernet запозичив в телефонних мереж ідею комутації, та з’явився свіч (мережевий комутатор). На відміну від концентратора, свіч посилає кадр лише тій станції, якій він призначений. А також, на відміну від хаба, в свічі кожна станція потрапляє у свій простір колізій, тому їх кількість зменшується до одиниці. Так як кадри з різних портів можуть прямувати на один порт, свіч містить буфер і відправляє їх по черзі. Ще одна корисна властивість свіча – він запобігає підслуховуванню чужих кадрів за допомогою адаптера в promiscuous mode.

До свіча можна приєднати хаб, таким чином на одному порті свіча буде ніби кілька станцій. Свіч на це реагує просто ігноруючи кадри, які адресуються станції підключеній до того самого хаба що й станція яка відправила кадр.

Хоча сьогодні, хаби (концентратори) майже зовсім не використовуються, тому можна вважати що один кабель завжди з’єднує лише два пристрої.

Fast, Gigabit Ethernet

Після того як з’явився комутований Ethernet, швидкість мережі перестала падати за нелінійним законом при приєднанні нових комп’ютерів і люди почали звикати до швидкості 10 Мбіт/c.

В 1992-му IEEE доручив комітету 802.3 створити новий стандарт, помноживши швидкість на 10. В 1995-му вийшов стандарт 802.3u, відомий в народі як Fast Ethernet. Який дозволяв передавати дані зі швидкістю 100 Мбіт/с. Свічі звісно мусили підтримувати обидва стандарти і щоб визначити який з них можна застосовувати на порті використовували процедуру яка називається “autonegotiation”.

Далі Fast Ethernet звісно став недостатньо швидким, і його знову вирішили помножити на 10. В 1999 IEEE випустили стандарт 802.3ab, або Gigabit Ehternet, що передавав 1 Гбіт/с, як не важко було здогадатись. В ньому заборонили використовувати концентратори і дуже скоротили кабелі (максимальна довжина 25м), тому що при такій швидкості можна відправити цілу купу кадрів до того як проявляться перші ознаки того що відбувається колізія. (мінімальний розмір кадру – 64 байти.)

Але 25 метрів це дуже мало, тому щоб збільшити, до стандарту дописали що можна дописувати ще одне поле, яке розширяє кадр до 512 байт (carrier extension) і використовувати кабелі до 200м. Але передавати 512 байт, де корисні лише 64 дуже неефективно. тому також пробували склеювати кадри в пакети (frame bursting).

Також в Gigabit Ethernet є функція контролю потоку. Якщо кадри йдуть з Gigabit в класичний Ethernet, свіч може послати передавачу на Gigabit порті кадр PAUSE (кадр в якому в полі тип написано 0x8808), щоб передавач пригальмував.

А далі, в 2002, 2004 та 2006 роках з’явились стандарти 10-гігабітного Ethernet для оптоволокна, екранованого мідного кабелю і мідної витої пари. І працюють над ще швидшими! Але ми в ті деталі сьогодні не вдаватимемось.

Мости

Коли ми розглядаємо мережі, треба завжди розглядати два аспекти – фізичний і логічний. Фізичний – це те як ми прокладаємо кабелі і які пристрої ними з’єднуємо. Логічний – як кадри всередині кабелів рухаються і комутуються насправді. Ми можемо як розділити одну фізичну мережу на кілька логічних, так і з’єднати кілька фізичних в одну логічну. Мости займаються останнім.

До появи комутованого Ethernet, мережа – це був кабель, в який комп’ютери вгризались за допомогою пристрою що називався “вампірчик” (прочитайте про кабель 10BASE5). Але кабель має обмежену довжину, і йому дозволено обмежену кількість повторювачів. Так само організація може займати кілька приміщень, і помістити всі комп’ютери в одну мережу, хай навіть і за допомогою комутатора, буде накладно. В таких випадках кожне приміщення отримує фізичну мережу, які з’єднуються між собою за допомогою моста.

Міст працює в нерозбірливому режимі (promiscuous mode), тобто приймає всі кадри, не залежно від того кому він призначався. І далі вирішує що з ним робити, шукаючи потрібну інформацію в спеціальній таблиці.

При приєднанні моста до мереж, ця таблиця порожня. Як тільки на якийсь з портів приходить кадр, міст запам’ятовує в таблиці MAC-адресу відправника і номер порта, і розсилає кадр на всі порти окрім того на який кадр прийшов (як хаб).

Якщо хтось відповідає, і просить прислати кадр на MAC-адресу яка мосту вже відома, міст шле кадр лише на відому адресу.

Якщо з якоїсь MAC-адреси вже кілька хвилин не приходили кадри, міст видаляє запис з таблиці, таким чином якщо фізична конфігурація мережі змінюється, міст сам за кілька хвилин переучується.

У вас напевне виникло питання “А чим відрізняється міст і комутатор?”. А тим самим що й ноутбук та лептоп – в слові комутатор більше букв :). Просто дві різні назви з’явились історично.

Метою мостів було з’єднувати різні мережі (наприклад Token Ring і Ethernet), але виходило погано, тому переважно вони з’єднували однокабельні Ethernet мережі, або Ethernet мережі з концентраторів. А метою комутаторів було замінити концетратори, які мали обмеження на число з’єднань пов’язане з котролем доступу до середовища. Але в кінці вийшло одне й те ж.

Spanning tree protocol (STP)

Слово “міст” (bridge) використовується й досі, тому що його використовують в актуальних досі стандартах, наприклад IEEE802.1D. Це стандарт що описує те як повинні працювати мости, і зокрема, такі деталі як протокол кістякового дерева.

Ми можемо з’єднувати два мости (концентратори) більш ніж одним кабелем для збільшення надійності з’єднання. Але тоді з’являється проблема – широкомовні кадри зацикляться, бо міст отримуватиме кадр через один порт і відправлятиме на всі інші, таким чином, якщо два мости з’єднані через два порти, вони пересилатимуть цей кадр одне одному, і всім іншим приєднаним пристроям до нескінченності.

Тому, мости домовляються ігнорувати лінії які не входять в кістякове дерево. Для цього, обирається кореневий свіч (свіч з найменшим ID, яким є MAC), і знаходяться всі найкоротші (найшвидші) лінії які ведуть від кожного пристрою до кореневого свіча. Це й є кістякове дерево.

Радья Перлман що придумала цей алгоритм змогла також віршик написати:

A tree that must be sure to span
So packets can reach every LAN.
First, the root must be selected.
By ID, it is elected.
Least-cost paths from root are traced.
In the tree, these paths are placed.

Взагалі, хотів би я вміти писати вірші. Їх справді легше й веселіше запам’ятовувати. Саме за допомогою вірша я вперше зміг запрограмувати рендеринг фракталу Мандельброта.

VLAN

Окрім того що багато фізичних локальних мереж можна об’єднати в одну логічну, можна також поділити одну фізичну, на багато логічних. Причин для цього є кілька:

  • Безпека (ізоляція даних)
  • Зменшення навантаження при доставці широкомовних пакетів. Такі пакети часто зустрічаються, бо потрібні наприклад для роботи протоколу ARP.
  • Локалізація можливого широкомовного шторму та інших неполадок.
  • Працівник може перевестись з одного офісу в інший (наприклад ближче до дому), і потрапити в іншу фізичну мережу. Але йому все одно треба бути в логічній мережі свого відділу.

Всі ці проблеми намагається вирішити технологія VLAN (віртуальної локальної мережі).

Комутатор що підтримує VLAN позначає (“зафарбовує”) кожен порт, як такий що належить певній VLAN (або кільком). На схемах VLAN позначають кольором, щоб можна було одночасно відобразити фізичну і логічну топології. Якщо приходить кадр з наприклад “червоної” VLAN, і він широкомовний, або порт для MAC-адреси отримувача невідомий, то його відправляють на всі порти які належать “червоній” VLAN.

Що робити якщо порт прибуває через порт що належить кільком VLAN? Кадр може належати лише одній мережі, але якій? Для цього, IEEE погодився змінити формат кадру Ethernet і додати туди нове поле. Стандарт випущений в 1998 назвали IEEE 802.1Q.

Найважчим питанням було, а що робити з мільйонами мережевих плат які не підтримують цей формат кадру? Щоб не викидати існуюче мережеве обладнання вирішили що перший комутатор на шляху кадра, що сумісний з VLAN буде додавати в кадр ідентифікатор VLAN, а останній – забирати. Таким чином на кінцеве обладнання потрапляють кадри звичайного формату.

VLAN який присвоюють кадру визначають за тим з якого порта він прийшов, або за протоколом вищого рівня. Наприклад можна послати всі кадри що містять IP в одну мережу, а кадри з PPP – в іншу. Було б зручно також визначати VLAN за MAC-адресою (наприклад якщо ноутбук часто змінює порти), але стандарт 802.1Q такого не передбачає.

Поле ідентифікатора для VLAN займає 12 біт. Таким чином загальна кількість можливих VLAN – 4096. Цього недостатньо для хмарних сервісів які дозволяють створювати мільйони віртуальних серверів і мереж, тому для них придумали іншу технологію віртуалізації – VXLAN (Virtual eXtensible LAN). Але в ній вже самі кадри віртуальні і передаються всередині TCP-пакетів. Віртуалізується віртуальна мережа. :)

Вищі рівні

Мости/комутатори це пристрої другого рівня. Вони дивляться на заголовки кадрів і таким чином вирішують що з ними робити. Концентратори і повторювачі – пристрої першого рівня. Вони просто приймають і передають сигнали, не особливо задумуючись над тим що ті сигнали означають.

З’єднати мережі з різними протоколами складно, бо переклад навіть чогось формального – дуже складна задача. Це ускладнюється різним максимальним розміром порції даних дозволених для передавання (MTU), різною схемою адресації і багато чим іншим. Але крім трансляції одного протоколу в інший, є ще один спосіб.

Щоб справді з’єднати мережі різного типу (наприклад 802.11 (Wi-Fi), 802.3 (Ethernet) та MPLS (швидкісний протокол що з’єднує комутатори провайдерів)), треба використати ще один рівень абстракції. Навіть якщо на другому рівні пристрої адресуються не за допомогою MAC, вони все одно адресуються спільними адресами третього рівня (наприклад IP). На цьому рівні абстракції працює маршрутизатор (router). Він відкидає всі заголовки кадрів другого рівня, і дивиться в їх вміст. А вміст – це датаграма третього рівня, і її заголовки вона описують куди її відправити.

Існують також пристрої ще вищого рівня, які називаються шлюзами. Існують шлюзи транспортного рівня, що дозволяють перетворювати дані з одного протоколу в інший, або шлюзи прикладного рівня, що, наприклад перетворюють SMS-повідомлення в E-mail.

Джерела

Всіх посилань не даю, бо їх забагато. В основному “Комп’ютерні мережі” Танненбаума і вікіпедія.

До читачів

Cподіваюсь я не переобтяжив ваші мізки інформацією і загальні принципи ви зрозуміли. Дякую що дочитали сюди і не заснули. І пробачте що так мало картинок – мені треба оновити свою стару Xubuntu 12.04, і подивитись чи в ній працюватиме графічний планшет. Тоді сподіваюсь цей блог стане більш ілюстрованим.

Якщо маєте ще якісь питання – питайтесь, я поки це все писав, таки трохи розібрався. Деталі звісно на вікіпедії, і якщо читатимете її українською, почистіть трохи те що читатимете, бо в телекомунікаціях там такий срач, що руки за голову хапаються.


Filed under: Конспекти, Павутина Tagged: hardware

Stm32 Nucleo – вхідні сигнали і комунікація з компю’тером

Сьогодні продовжимо розбиратись з нашою платою, і почнемо з того, як отримати натиснення кнопки. Якщо вас цікавить початок – переходьте сюди.

Якихось чітких інструкцій в інтернеті я не знайшов, зате в IDE було аж два демо проекти про кнопку:

  • “Read the user button state on the Nucleo board.”
  • “Read the user button using external interrupt.”

Код там досить простий, але я його ще спростив ось так:

#include "mbed.h"
 
DigitalIn mybutton(USER_BUTTON);
DigitalOut myled(LED1);
 
int main() {
  while(1) {
    myled = mybutton;
  }
}

Тобто так само як ми оголошуємо що змінна myled міститиме рівень напруги на світлодіоді, так само ми оголошуємо що змінна mybutton міститиме рівень напруги на кнопці.

В документації по mbed написано що оголошення DigitalIn можна використовувати на будь-якому виводі, який позначений на схемі синьою міткою. Якщо на вході будь-яка напруга менше 0.8В – міститиме 0, якщо більше 2В – міститиме 1.

Що цікаво, коли я записав вищеподану програму на плату, світлодіод почав світитись, і почав вимикатись лише коли кнопка натиснута. Це пояснюється чудернацькою схемою підключення кнопок – якщо вона розімкнута – на вхід через резистор йде струм. Якщо замкнута – вхід заземляється, і струм йде в землю, тому там нуль.

Інший приклад – з перериванням:

#include "mbed.h"
 
InterruptIn mybutton(USER_BUTTON);
DigitalOut myled(LED1);
  
void pressed()
{
    myled = !myled;
}
 
int main()
{
    mybutton.fall(&pressed);
    while (1) { // без цього - не працює
        wait(100);
    }
}

Тут з кожним натисканням кнопки світлодіод вмикається або вимикається. Зауважте що тепер ми оголошуємо кнопку не як DigitalIn, а як InterruptIn.

Ок, може пора нарешті попрацювати руками? Хоча страшно, бо кажуть що руками ту плату можна й вбити, якщо створити коротке замикання в неправильному місці. Я от наприклад вирішив спробувати як вона працює окремо від комп’ютера, і замість того аби втикнути USB в комп’ютер, втикнув його в адаптер електричної мережі. Адаптер, як на ньому написано повинен був давати 5.1В 850мА постійного струму. Плата не захотіла моргати до мене світлодіодами, як було запрограмовано, просто LD1 (COM) загорівся загрозливим червоним. Тому напевне спершу піду ще раз інструкцію прочитаю.

Схема виходів. В коді дозволяється використовувати лише ті що написані білим в синіх і зелених прямокутничках.

Шкода що не маю мультиметра, можна було б подивитись яка напруга на яких контактах.

З того що я начитався, виходить що там де написано 5v – є напруга 5В, там де 3V3 – 3.3В. (такий запис – це хитрий спосіб прибрати зайвий символ – десяткову крапку, і зробити підпис компактнішим.) До п’ятивольтового контакту світлодіоди краще приєднувати через резистор. GND – це заземлення (мінус).

В світлодіода довша ніжка – це +, коротша -, або та ніжка що всередині корпусу діода має в собі більше металу – це мінус.

І це можна перевірити, втикаючи світлодіод в 3V3 та GND. Або послідовно з резистором в 5V та GND.

Тепер, давайте зробимо так, щоб наш перемикач з останнього лістингу керував зовнішнім світлодіодом. Для цього втикаємо його мінус в GND, в A5 наприклад втикаємо резистор, і з’єднуємо додатню ніжку діода з резистором.

Замінюємо визначення: DigitalOut myled(LED1); на DigitalOut myled(PC_0);. Перепрошиваємо, і тепер вже зовнішній світлодіод повинен реагувати на нашу кнопку.

Далі я написав програмку яка змушувала б вбудований LED показувати стан піна A5 як входу.

#include "mbed.h"
 
DigitalIn mycontact(PC_0);
DigitalOut myled(LED1);
  
int main() {
    while (1) {
        myled = mycontact;
    }
}

І дуже здивувався, бо коли я опускав туди лише одну ніжку резистора – діод засвічувався. Я подумав що струм тече в мене як заземлення і відпустив резистор – діод все одно світився. Дивно. Або я ще чогось не знаю, або в платі якийсь брак. Думаю варто переключитись на вбудовану кнопку до з’ясування обставин.

Що ще хотілось би зробити – так це взаємодію з комп’ютером. Нехай по натисненні кнопки, комп’ютер виконує якусь команду.

Виявляється, що при приєднанні контролера до комп’ютера, він окрім того що розпізнається як диск, ще й додає пристрій який називається /dev/ttyACM* (замість зірочки має бути якесь число). Принаймі так написано в документації.

Ми можемо подивитись що на цьому пристрої, за допомогою команди:

sudo cat /dev/ttyACM0

Якщо треба вийти, то натискаємо Ctrl+A а тоді вводимо команду :quit. Тепер, можемо змусити контролер посилати нашому комп’ютеру всілякі повідомлення по натисненні кнопочки:

InterruptIn mybutton(USER_BUTTON);
Serial pc(USBTX, USBRX);

void pressed()
{
    pc.printf("I'm clicked!\r\n");
}
 
int main()
{
    mybutton.fall(&pressed);
    while (1) { wait(100); }
}

І ми побачимо щось таке:

$> sudo cat /dev/ttyACM0 
I'm clicked!
I'm clicked!
I'm clicked!

І тепер, ми можемо змусити якийсь процес читати цей пристрій і виконувати з нього команди. Наприклад такий Python скрипт:

import os
with open('/dev/ttyACM0', 'rb', 0) as f:
    while True:
        message = f.read(5) # reading 5 byte messages
        if message == 'ALARM':
            os.system('mplayer -fs /home/bunyk/video/beastie_boys_sabotage.flv')

Замінюємо повідомлення з "I'm clicked!\r\n" на І вийде просто чудова кнопка тривоги наприклад:


Filed under: Інструменти, Кодерство, Конспекти Tagged: C++, hardware

Привіт “ядерному мікроконтролеру” ;)

Вкотре переконуюсь що якщо чогось дуже хочеш – то отримаєш. Так от я хотів якось спробувати скласти гірлянду якою можна буде керувати з комп’ютера, трохи думав про Arduino, і недавно мені в руки для тестування потрапила плата NUCLEO-F411RE від компанії STMicroelectronics. Все завдяки автору сайту embedded.co.ua, Василю Йосипенку, якому за це величезне дякую.

nucleo

Почну з того що на платі надруковане посилання: www.st.com/stm32nucleo. І наклеєна наклейка NUCLEO-F411RE. З діаграми на сайті видно що F411 це найшвидша плата, яка має найбільший розмір флеш-пам’яті – 512K. Аж пів метра!

Далі я звісно перейшов на сторінку плати і почав RTFM. Ось інструкція.

Там в розділі Getting Started знайшов таке:

  1. Перевірте наявність на платі джамперів:JP1 знятий, JP5 (PWR) в позиції U5V, JP6 (IDD) вставлений, CN2 вставлені (NUCLEO). Їх довелось довго шукати, бо всіляких конекторів резисторів та інших деталей на платі трохи є, і вони досить дрібненькі. Але коли я приблизно вивчив їх розташування, виявилось що вже все правильно встановлено.
  2. Для коректної ідентифікації пристрою встановіть драйвери з сайту.Для Linux їх я там не знайшов, тому забив. Але виявилось що й без того мій Linux розпізнав цю плату як диск. На ньому виявився невеликий файл mbed.html, що перенаправляв на https://developer.mbed.org/platforms/ST-Nucleo-F411RE/
  3. Приєднайте плату до комп’ютера за допомогою USB-кабеля type A to mini B. Через USB коннектор CN1. Засвітиться червоні світлодіоди LD3 (PWR) та LD1 (COM). LD1 та зелений світлодіод LD2 повинні мигати. Кабель на щастя знайшовся. Добре мати сусіда-фотографа.
  4. Натисніть кнопку B1 (ту що зліва) і спостерігайте як вона змінює частоту мигання LD2. Вона працює!
  5. Дивіться демо програмки, пишіть свої. Яволь! Заради цього я й відкрив інструкцію.

Далі в інструкції я того як залити програмки не знайшов, погуглив, знайшов хабр. Вони хоч і москалі, але написали непогану невелику інструкцію про те як почати бавитись з Nucleo-F401. Тут приведу її скорочений варіант.

  1. Щоб почати розробляти з mbed.org – треба зареєструватись на сайті mbed за оцим посиланням.
  2. Коли зареєструвались, натискаємо вкладку Platforms, і знаходимо там ST-Nucleo-F411RE.
  3. На сторінці нашої плати справа натискаємо синю кнопку “Add to your mbed compiler”.
  4. Вгорі натискаємо посилання Compiler.
  5. Відкривається симпатичне браузерне IDE. В головному меню натискаємо кнопку “New”.
  6. В вікні нового проекту залишаємо платформу ST-Nucleo-F411RE, вибираємо template “Blinky LED test for the ST Nucleo Boards”, виписуємо собі якесь ім’я програми і натискаємо “OK”.
  7. Створюється проект всередині якого є файл main.cpp, що містить наступний код:
    #include &quot;mbed.h&quot;
    
    DigitalOut myled(LED1);
    
    int main() {
        while(1) {
            myled = 1; // LED is ON
            wait(0.2); // 200 ms
            myled = 0; // LED is OFF
            wait(1.0); // 1 sec
        }
    }
    
  8. Натискаємо кнопку “Compile”. Через деякий час, якщо не сталось ніяких помилок, браузер пропонує нам завантажити файл Nucleo_blink_led_NUCLEO_F411RE.bin, чи з подібною назвою, залежно від того як ви назвали свою програму.
  9. Зберігаємо цей файл прямо в директорію /media/NUCLEO. Так, не треба писати образ ні на які пристрої за допомогою dd, просто скидуємо файл. Червоний світлодіод LD1 (COM) почне мигати зеленим, що означає що дані пишуться.
  10. Коли COM припинить мигати, частота мигання LD2 зміниться, і він перестане реагувати на натискання кнопки B1, а це означає що прошивка змінилась. Ура! Вперше якась мікросхема мигає світлодіодом так як я їй сказав. В директорії /media/NUCLEO ніякого нашого файлу видно не буде, що означає що це таки емуляція диску. Думаю не варто туди якісь інші файли кидати, а то ще не так перепрошиється.

Хоча ні, мигає вона ще не так як я сказав, а так як в прикладі показано. Якщо в нас як пристрій виводу – лише одна лампочка, то крім коду Морзе варіантів мало.

hello world на морзянці виглядає так:
…. . .-.. .-.. — / .– — .-. .-.. -..

Hello world нам моргає

Hello world нам моргає

Прогалик розділяє букви, / – розділяє слова.

Існує такий стандарт:

  1. Довжина крапки – 1
  2. Довжина тире – 3
  3. Відстань між частинами однієї букви – 1
  4. Відстань між окремими буквами – 3
  5. Відстань між словами – 7

Зібравши це все до купи, і так як в прикладі програми було щось схоже на C, і назва файлу main.cpp теж натякає, переклавши все на C, отримаємо таке:

#include &quot;mbed.h&quot;

DigitalOut myled(LED1);

const float DOT_DURATION = 0.5;

void morse(char *code, int len) {
    for(int i = 0; i &lt; len; i++) {
        switch(code[i]) {
            case '-': 
                myled = 1;
                wait(DOT_DURATION * 3);
                break;
            case '.':
                myled = 1;
                wait(DOT_DURATION);
                break;
            case ' ':
                myled = 0;
                wait(DOT_DURATION * 3);
                break;
            case '/': 
                myled = 0;
                wait(DOT_DURATION * 7);
                break;
        }
        myled = 0;
        wait(DOT_DURATION);
    }
};

int main() {
    while(1) {
        morse(&quot;.... . .-.. .-.. --- / .-- --- .-. .-.. -..&quot;, 43);
        wait(2.0);
    }
}

Ну ось, думаю поки що вистачить. Виявилось набагато простіше ніж я думав. Завтра спробую отримати ввід з вбудованої кнопки, і покерувати зовнішнім світлодіодом, а то вбудовані вже спаяні до мене, і ні про який закон Ома думати не треба. На щастя світлодіоди разом з резисторами і метром проводу для них коштують дешевше ніж поїздка в трамваї, тому дістати їх – нема проблеми. Хоча сама плата в Україні коштує більше ніж 600 грн: http://www.kosmodrom.com.ua/prodlist.php?name=nucleo

Продовження


Filed under: Інструменти, Кодерство, Конспекти Tagged: C++, добре, hardware

Німецьке QWERTY

Німці використовують деякі букви, яких нема в стандартній латинській розкладці: ÄÖÜẞ, тому існує окрема німецька розкладка. Але біда, біда, вона не QWERTY, а QWERTZ, і Z та Y поміняні місцями. Правильної розкладки чомусь нема, тому я вирішив зробити свою. Має працювати на всіх системах що використовують X keyboard extension з X Window System.

Замість кнопки “-” отримуємо “ß”, замість “[” – “Ü”, “;” – “Ö” ну а замість “‘” – “Ä”. Всі інші залишаються на місці, а не перескакують чорт зна куди як в традиційній німецькій розкладці.

Відкриваємо розкладки для Німеччини:

cd /usr/share/X11/xkb/
sudo vim symbols/de

Додаємо розкладку з наступними клавішами (наслідується від базової американської):

xkb_symbols "germanqwerty" {
    include "us(basic)"
    name[Group1]="German (QWERTY)";

    key <AD11>	{ [udiaeresis, Udiaeresis, dead_diaeresis, dead_abovering ] };
    key <AC10>	{ [odiaeresis, Odiaeresis, dead_doubleacute, dead_belowdot ] };
    key <AC11>	{ [adiaeresis, Adiaeresis, dead_circumflex, dead_caron ] };
    key <AE11> {type[Group1]="FOUR_LEVEL_PLUS_LOCK",  symbols[Group1]=
                  [ssharp, question, backslash, questiondown, 0x1001E9E ]};
};

Далі додаємо нову розкладку до списку відомих:

cd /usr/share/X11/xkb/
sudo vim rules/evdev.xml

Знаходимо список розкладок для Німеччини і додаємо туди свій варіант:

        <variant>
          <configItem>
            <name>germanqwerty</name>
            <description>German (QWERTY)</description>
          </configItem>
        </variant>

Далі треба розлогінитись і залогінитись заново, і можна додавати розкладки через аплет панелі робочого стола.

Посилання


Filed under: Кодерство, Конспекти Tagged: deutsch, linux

Вступ до PowerShell

Зробив на роботі доповідь по PowerShell:

І не переживайте, там з восьмої хвилини в конференції нарешті настає тиша. :)

Презентація зроблена на основі вікіпідручника з PowerShell, який порізано на слайди і показано за допомогою deck.js (хоча про технологію якось іншим разом).

Це приклад того як доповіді робити не варто. Не варто змішувати підручник і презентацію, на презентації повинен бути лише код, картинки і максимум одне-два слова тексту. І якщо все таки якийсь текст вже є – не можна його читати. Ваші слухачі грамотні все таки.

З іншого боку – краще зробити щось неідеально, ніж не зробити ідеально. :)

Є інший приклад: Александр Соловьев — Functional Reactive Programming & ClojureScript. Чувак не париться, лише 16 слайдів, видно що тема його вставила, але пояснити він її може заледве на пальцях. Проте я таки зрозумів що FRP – це як в Excel, і при цьому не заснув.

P.S. Наступна доповідь буде кращою. :)


Filed under: Кодерство, Конспекти Tagged: освіта, робота, windows

Як динамічно зібрати клас з функцій?

Це може дозволити повторне використання коду ще краще за звичайне OOP з наслідуванням.

Що найважливіше знати про Python? Те що код в блоці class – це такий самий код як і в модулі, просто виконується в просторі імен модуля. І функції там звичайнісінькі.

А щоб перенести something з простору імен класу в простір імен модуля, досить написати в класі просто something = something. Ось так:

def say(self, what):
    print self.name, 'says', what

class Human(object):
    def __init__(self, name):
        self.name = name
    print __init__ # <function __init__ at 0x7fdc3ba25758>
    say = say # here we move say into class namespace
    print say # <function say at 0x7fdc3bb1e1b8>

me = Human('Bunyk')
print me.say # <bound method Human.say of <__main__.Human object at 0x7fdc3ba2a310>>
me.say('hello') # Bunyk says hello

Ще ми бачимо що метод стає прив’язаним до об’єкта, власне коли цей об’єкт створюється класом. А в класі це не метод, це просто функція собі.

Правда я подумав що вираз something = something може спантеличити математиків і вони надовго задумаються над його значенням, і написав міксін, бо паттерни всі знають і люблять. :)


Filed under: Кодерство, Конспекти Tagged: Python